はじめに
風邪引いてダウン中です。
kojirockです。
今回はめちゃめちゃ簡単なものです。
よくある検索機能で検索パラメータが複数あるようなのがあると思います。
今回、別ページでもその検索パラメータが使えるような要件がありました。
それぞれのAPIで検索パラメータによってwhere句をつけるif文の塊をコピペしてたのですが、criteria的な感じで共通化できないか?というお話をチームメンバーの方に相談されて、調べてやってみました。
結果、実態はscopeですが、なんとなく出来たので、忘れないようにブログにします。
やってみた
こちらのレポジトリを参考にさせていただきました。レポジトリには他にもAllOfCriteriaCollection.phpなどもあったのですが、もっと薄くてよかったので、Criteriaとして使えるものだけピンポイントだけ使わせてもらいました。
CriteriaInterface.php
<?php namespace App\Criterias; use Illuminate\Database\Eloquent\Builder; interface CriteriaInterface { /** * @param Builder $query */ public function append(Builder $query); }
CriteriaTrait.php
<?php namespace App\Criterias; use App\Eloquents\Builder\CustomBuilder; use Illuminate\Database\Eloquent\Builder; /** * Trait CriteriaTrait * @package App\Criterias * @method CustomBuilder query() * @method CustomBuilder newQuery() * @method CustomBuilder newModelQuery() */ trait CriteriaTrait { /** * @param Builder $query * @param CriteriaInterface $criteria * @return Builder */ public function scopeCriteria(Builder $query, CriteriaInterface $criteria): Builder { $criteria->append($query); return $query; } /** * Create a new Eloquent query builder for the model. * * @param \Illuminate\Database\Query\Builder $query * @return \Illuminate\Database\Eloquent\Builder|static */ public function newEloquentBuilder($query): Builder { return new CustomBuilder($query); } }
SearchUserCriteria.php
<?php namespace App\Criterias; use Illuminate\Database\Eloquent\Builder; class SearchUserCriteria implements CriteriaInterface { /** * @var array */ private $parameters; /** * SearchUserCriteria constructor. * @param array $parameters */ public function __construct(array $parameters) { $this->parameters = $parameters; } /** * @param Builder $query */ public function append(Builder $query) { // 検索パラメータによってwhere句を追加 } }
CustomBuilder.php
<?php declare(strict_types=1); namespace App\Eloquents\Builder; use App\Criterias\CriteriaInterface; use Illuminate\Container\Container; use Illuminate\Database\Concerns\BuildsQueries; use Illuminate\Database\Eloquent\Builder; /** * Class CustomCriteriaBuilder * @package App\Eloquents\Builder * @method \Illuminate\Database\Query\Builder criteria(CriteriaInterface $criteria) */ class CustomBuilder extends Builder { }
EloquentUser.php
<?php declare(strict_types=1); namespace App\Eloquents; use App\Criterias\CriteriaTrait; use Illuminate\Database\Eloquent\Model; /** * Class EloquentUser * @package App\Eloquents */ class EloquentUser extends Model { use CriteriaTrait; protected $table = 'users'; protected $fillable = ['email', 'password']; public function searchUsers(array $parameters): array { return self::query() ->criteria(new SearchUserCriteria($parameters)) ->paginate(15); } }
終わりに
補完を効かせなくてよければ、CustomBuilderを作る必要はないです。
自分の場合はストレスだったので作りました。
あと、CustomBuilderつくっとけば、たとえば Paginatorの返却クラスも上書きできたりするので、便利でした。
もっと他に良さげなやり方あれば教えて下さい。。。