[Học Laravel] Model search với Laravel searchable

[Học Laravel] Model search với Laravel searchable

Trong bài viết này mình sẽ giới thiệu về thư viện Laravel searchable, ra đời vào cuối năm 2018, đây là một thư viện hỗ trợ chức năng tìm kiếm đơn giản trên model.

1. Cài đặt

1.1 Tạo dự án và các model

Tạo mới một dự án laravel

composer create-project laravel/laravel Laravel-searchable-demo

Sau đó cd vào thư mục dự án và cài đặt laravel searchable bằng lệnh sau

composer require spatie/laravel-searchable

Trong project này mình sẽ tạo hai model phục vụ cho mục đích demo là category và product có mối quan hệ một nhiều. Mình sẽ tạo các file migration và model sử dụng các lệnh dưới đây:

php artisan make:model Product -m
php artisan make:model Category -m

Các câu lệnh trên sẽ sinh ra 2 file migration với tên có dạng là xxxxx_create_products_table.php và xxxxx_create_categories_table.php trong thư mục databasemigrations và 2 file model là Product.php và Category.php trong thư mục app.

Chỉnh sửa nội dung các file migration của product và category như sau

  • xxxxx_create_products_table.php
Schema::create('products', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->text('description');
            $table->string('image')->nullable();
            $table->bigInteger('category_id');
            $table->decimal('amount', 8, 2);
            $table->timestamps();
            $table->softDeletes();
        });
  • xxxxx_create_categories_table.php
Schema::create('categories', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->text('description');
            $table->timestamps();
 });

Sau đó chạy lệnh sau để tiến hành tạo table trong database

php artisan migrate

Và chỉnh sửa nội dung các file model Product.php và Category.php như sau:

  • Product.php
belongsTo('AppCategory');
    }

    public function getSearchResult(): SearchResult
    {
        $url = route('products.show', $this->id);

        return new SearchResult(
            $this,
            $this->name,
            $url
        );
    }
}
  • Category.php
hasMany('AppGift');
    }

    public function getSearchResult(): SearchResult
    {
        $url = route('categories.show', $this->id);

        return new SearchResult(
            $this,
            $this->name,
            $url
        );
    }
}

$url ở đây là một biến string mình suwur dụng để lưu lại đường dẫn đến trang show của model hiện tại phục vụ cho việc đi tới trang detail của model sau này, bạn có thể không cần truyền url nếu không cần sử dụng.

1.2 Cấu hình cho Controller, Routes, và View

Tiếp theo, mình sẽ tạo chức năng hiển thị product và tìm kiếm.

Tạo controller

php artisan make:controller SearchController

Trong controller, tạo 2 action là index để hiển thị view và search để thực hiện chức năng tìm kiếm

input('query');

        $searchResults = (new Search())
            ->registerModel(AppProduct::class, ['name', 'description']) //apply search on field name and description
            //Config partial match or exactly match
            ->registerModel(AppCategory::class, function (ModelSearchAspect $modelSearchAspect) {
                $modelSearchAspect
                    ->addExactSearchableAttribute('name') // only return results that exactly match
                    ->addSearchableAttribute('description'); // return results for partial matches
            })
            ->perform($searchterm);

        return view('search', compact('searchResults', 'searchterm'));
    }
}

Ta có thể đăng ký các model sẽ được áp dụng search bằng phương thức registerModel với tham số thứ nhất là tên của model class và tham số thứ 2 là các thuộc tính sẽ được chỉ định để search, có thể đăng ký nhiều model bằng cách gọi nhiều lần hàm registerModel và cuối cùng truyền từ khóa để search vào phướng thức perform.

Ở đoạn code trên, khi sử dụng hàm registerModel như mình đã đăng ký cho model ‘Product’, mặc định cơ chế search sẽ là search like, còn trong trường hợp bạn muốn search chính xác thì có thể custome lại bằng cách sử dụng ModelSearchAspect như mình đã đăng ký cho thuộc tính name của model Category. Hiện tại laravel searchable chỉ hỗ trợ searh likeexact match

Tạo một file view có tên search.blade.php trong thư mục resourcesviews để hiển thị dữ liệu

search.blade.php


@if(isset($searchResults)) @if ($searchResults-> isEmpty())

Sorry, no results found for the term "{{ $searchterm }}".

@else

There are {{ $searchResults->count() }} results for the term "{{ $searchterm }}"


@foreach($searchResults->groupByType() as $type => $modelSearchResults)

{{ $type }}

@foreach($modelSearchResults as $searchResult) @endforeach @endforeach @endif @endif

Ở đây $searchResults là một instance của lớp SearchResultCollection, nếu bạn muốn tìm hiểu sâu hơn có thể tham khảo trong source code của thư viện tại đây

Đăng ký route trong file web.php

Route::get('search', '[email protected]')->name('search.index');
Route::get('search-results', '[email protected]')->name('search.result');

Bây giờ mình sẽ tạo dữ liệu mẫu như sau

Table categories

Table products

Và kết quả

2. Kết

Laravel Searchable gúp bạn giải quyết nhanh về chức năng search, thích hợp cho các dự án nhỏ chỉ yêu cầu về các chức năng search like và exact cho nhiều model.

Bạn có thể đóng góp thêm cho thư viện này tại đây https://github.com/spatie/laravel-searchable

admin

Leave a Reply

Your email address will not be published. Required fields are marked *