CakePHP Searchプラグインで 複数Modelを検索
CakePHP Searchプラグインで 複数Modelを検索
ああ!Searchプラグイン!君無しでは検索できない!
もうね、便利すぎて検索フォームとか自作する気ないわ。何かもうかあさんの人生にSQLが必要無いわ(エンジニアとしてそれはどうかと。。
検索がとっても便利なSearchプラグインの基本的な使い方はこちら
基本的な使い方は上記サイトがとてもきれいにまとめてあるのでそちらを参照してください。
かあさんの方は複数モデルを扱っているケースで、アソシエーションされている方のModelのデータをSearchプラグインを使って検索する方法です。
例として、ブログ的なPostModelとUserModelがあったとして、PostModelからも著者であるUserModelも両方ともSearchプラグインの検索対象としたい場合を想定します。
Controller
※Search Compornentは各自呼んでおくようにしてくださいな。
public function index() { $this->paginate = array( 'conditions' => $this->Post->parseCriteria($this->passedArgs), 'limit' => 10, ); $this->set('courses', $this->Paginator->paginate()); }
Controllerは特に変わったことはありません。要するに、Searchプラグインで、Postにアソシエーションされているデータを検索したいのです。
Model
複数Modelに股がって検索したい時は、アソシエーションされている方のModelではなく、アソシエーションしている方、今回だとメインはPostModelで、アソシエーションしているのがUserModelとします。
public $actsAs = array('Search.Searchable'); public $filterArgs = array( // search rules array('name' => 'title', 'type' => 'like', 'field' => 'Post.title'), array('name' => 'name', 'type' => 'like', 'field' => 'User.name'), );
fieldというオプションがあると知って、入れてみたら簡単に動きました。
nameとは、検索のgetパラメータにあたる部分。titleの検索対象はPostModelのtitleフィールドにするよ、という意味になります。
name属性とfield名は必ずしも同じ名前である必要はないの。ですから、titleのパラメータがあったら、PostModelのtitleフィールドを検索する、という意味になります。
view
viewはなんだか不思議な感じになります。
Form->create('Post');?> Form->input('title', array('div' => false, 'required' => false, 'placeholder' => 'title入力'));?> Form->input('name', array('div' => false, 'required' => false, 'placeholder' => '著者名入力'));?> Form->submit(__('Submit'));?>
すると出力されるHTMLは当然のことながらPostが主体になってしまいます。
でも、さきほどModelに、getパラメータのnameに 「name」が来たら、User.nameを検索してね!と記載したので大丈夫なんです。
もしも違うModelに同じフィールド名があって、それを検索対象としたい場合は、$filterArgsに対して都度Model名も書いてあげればよいわけです。分かると実に簡単!
Searchプラグインがますます大好きになりました