LoginSignup
27
17

More than 3 years have passed since last update.

Laravelで超簡単に検索機能を作成するPackageを作成した

Last updated at Posted at 2019-12-01

この記事はLaravel #2 Advent Calendar 2019の2日目になります。

検索機能?

Webアプリを作成していると、よく検索機能作成しますよね?
↓こんな検索画面です。
2019-12-01_21h39_47.png

このくらいシンプルであれば、ifやEloquentを使って条件を追加するのも悪くないですが、検索項目が多くなってきたり、複雑になってくると、途端に可読性が悪くなったり、めんどくさくなったりすると思います。

その為、Laravelの検索機能の作り方や、検索に特化したPackageなどを、ググったりしたのですが、簡単に検索を実装できるものがなかったので作ってみました。

作ったPackage

:sparkles:作るときに気にしたポイント

  • 簡単に検索機能を実装できること(検索実装の為に処理をなるべく書きたくない)
  • どんな状況にも柔軟に検索できること
  • Laravelっぽいこと

:sparkles:Seaaaaarchで出来るようになること

  • Searchableクラスを作成することで、検索条件を書く場所を別クラスに分けれる
  • 検索条件にcallbackを受け付けることで、柔軟に検索できる
  • 簡単な検索は設定を書くだけで検索を実装できる
  • Filterクラスを作成することで、検索条件を共通化できる

基本的な使い方

インストール

composer require fusic/Seaaaaarch

bladeの準備

index.blade.php等に検索用の画面を作成します。
ここは普通のbladeになります。
※名前と住所で検索することを想定

index.blade.php
<form action="{{ route('users.search') }}" method="post">
    @csrf
    <div class='row'>
        <div class='col-md-6'>
            <div class='form-group'>
                <input name="name" />
            </div>
        </div>
        <div class='col-md-6'>
            <div class='form-group'>
                <input name="address" />
            </div>
        </div>
    </div>
    <div style="text-align: center;">
        <button class='btn-default'>検索</button>
    </div>
</form>

Searchableの作成

Seaaaaarchをインストールすると、Searchableが作成できるようになります。
Searchableは検索の実態を記載するクラスになります。

php artisan make:searchable UsersSearch

シンプルな検索であれば、下記のような設定だけで検索を実装することが可能になります。

UsersSearch.php
<?php
namespace App\Search;

use Search\Searchable;

class UserSearch extends Searchable
{
    public function __construct()
    {
        $this->params = [
            // ここに検索条件を記載します
            // 名前 と 住所を検索できるようにします
            'name' => [
                // typeにvalueを設定すると、入力値を完全一致で検索します。
                'type' => 'value'
            ],
            'address' => [
                // typeにvalueを設定すると、入力値を部分一致で検索します。
                'type' => 'like'
            ],
        ];
    }
}

※検索用にvalue、like、in、callback等準備しています。
※Searchableの詳細な設定項目についてはSearchableの設定を参照してください。

コントローラーに検索用アクションを作成

検索用に、上記で作成したformからPOSTを受け取るアクションを作成します。
QueryParser::parse に Searchableクラス のインスタンスを渡すことで、POST値から検索に必要な値を取り出します。
※routesの設定してください。

UsersController.php
public function search() {
    $query = QueryParser::parse(new UsersSearch());
    return redirect()->route('users.index', $query);
}

検索の実行

SeaaaaachをインストールするとEloquentにsearchメソッドを追加します。
searchに対してSearchableインスタンスを渡すことで、 Searchableに設定された検索条件で検索を行います。
searchメソッドの前後にEloquentの機能で条件やソートなどを追加することも可能です。

UsersController.php
public function index() {
    UserModel::search(new UserSearch())->where('example', 'test');
    // or
    UserModel::where('example', 'test')->search(new UserSearch())
}

柔軟な検索

Searchableに検索条件を書くことになりますが、完全一致や部分一致ではなく、JoinやPHPの処理を挟む等複雑な処理をすることもあると思います。
そういう状況では、Searchableのcallbackを利用します。

callbackの引数に渡ってくる$builderでEloquentの機能を利用することが出来ます。

UsersSearch.php
<?php
namespace App\Search;

use Search\Searchable;

class UserSearch extends Searchable
{
    public function __construct()
    {
        $this->params = [
            'name' => [
                // typeにcallbackを指定すると、methodに検索処理を書くことが出来ます。
                'type' => 'callback',
                'method' => function (Builder $builder, $key, $value) {
                    // ここで条件を組み立てます
                    $name = mb_convert_kana($value, 'Hc');
                    $builder->where('name', $name);
                }
            ]
        ];
    }
}

処理の共通化

プロジェクト全体等、共通的に利用したい検索条件を作成する機能もSeaaaaarchは準備しています。
Filterクラスを作成することで共通化することが可能です。

Filterの作成

Filterを作成することで、検索条件を作成することが可能です。

php artisan make:filter ExampleFilter
App\Search\Filter\ExampleFilter.php
<?php
namespace App\Search\Filter;

use Illuminate\Database\Eloquent\Builder;
use Search\Filter\Filter;
use Search\Filter\FilterInterface;

class ExampleFilter extends Filter implements FilterInterface {
    protected $defaultOptions = [];

    public function process(Builder $builder, $field, $value)
    {
        // ここに検索条件の処理を記載します
        // 例:20歳以上を検索条件にする
        $builder->where('age', '>=', 20);
    }
}

Filterの使い方

UsersSearch.php
<?php
namespace App\Search;

use Search\Searchable;

class UserSearch extends Searchable
{
    public function __construct()
    {
        $this->params = [
            'age' => [
                // この指定で、20歳以上の条件がかかるので検索条件の共通化をすることが可能です。
                'type' => ExampleFilter::class
            ]
        ];
    }
}

その他細かい利用方法

GitHubに記載してありますので確認してください。
https://github.com/fusic/Seaaaaarch/tree/master/docs/ja

気に入ったらPull requestやstarよろしくお願いします :bow_tone1:

27
17
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
17