CakePHP3の検索プラグイン「friendsofcake/search」の設置方法・CakePHP3.6対応
2019/09/28
CakePHP3の検索プラグイン「friendsofcake/search」の設置方法
CakePHP3の検索プラグイン「friendsofcake/search」とは
CakePHP3で検索処理を実装するにあたってプラグインの利用を検討しました。
結果、CakePHP3の検索プラグインでは「friendsofcake/search」がメジャーなようでした。
CakePHP2の頃は「CakeDC/search」というプラグインを使っていまして、下記の記事などを書いていました。
CakePHP 2.3 Search Pluginで検索処理 その1設置方法
「CakeDC/search」同じ「CakeDC」のグループが作ったプラグインとしては、CakePHP3でも使っている「CakeDC/Users」というユーザ認証に関するプラグインがあります。
CakePHP3のユーザ管理・ログイン認証プラグインCakeDC/Usersのインストール解説・3.6以降対応
ですが、検索プラグインでは CakePHP3になってからは「friendsofcake/search」が主流となったようです。
「friendsofcake」というグループは「CakeDC」と同様、CakePHPを開発している方々が在籍しているグループのようです。
また、「friendsofcake」が作ったプラグインとしては、Bootstrapを組み込むためのプラグイン「friendsofcake/bootstrap-ui」などがあります。
CakePHP3にデザインテンプレートBootstrapを導入する方法・friendsofcake/bootstrap-ui使用
実際に「friendsofcake/search」を使ってみた感じでは、「CakeDC/search」よりも簡単に導入することができ、各条件に合わせたカスタマイズも簡単にできる感じがします。
検索処理のような汎用的な処理は、オリジナルの処理を作るよりプラグインを使うほうが効率的に開発を進めることができるでしょう。
ちなみに、CakePHP3.6になったときに「friendsofcake/search」の設置方法も変わったと思われ、CakePHP3.6がリリースされた 2018年4月14日以前に書かれた記事のソースコードでは動作しないものが多々ありました。
参考にする際は記事が書かれた日付を確認したほうが良さそうです。
この記事は、CakePHP3.7で動作確認しながら書いています。
CakePHP3の検索プラグイン「friendsofcake/search」の導入手順
この章では、「friendsofcake/search」を導入する基本的な手順を解説します。
次の章で、記述方法のバリエーションや不具合が発生した場合の対応方法について解説します。
1.Composerを使って「friendsofcake/search」をインストール
まずはじめに、下記のコマンドを実行し、「friendsofcake/search」をインストールします。
コマンドを実行する場所は、アプリケーションのルートフォルダです。
1 |
$ composer require friendsofcake/search |
CakePHP3でプラグインやライブラリをインストールする際には Composerを使うと便利ですが、これまでに Composerがよくわからない方は下記を参照してください。
CakePHP3でcomposerを利用してライブラリ・プラグインをインストールする方法
2.「friendsofcake/search」をロード
次に、インストールした「friendsofcake/search」をプログラム内で使用するためにロードする設定を記述します。
/src/Application.php
に下記の処理を追加します。
1 2 3 4 5 6 7 |
public function bootstrap() { : (既存の処理) : $this->addPlugin("Search"); // この行を追加する |
ここでは「/src/Application.php」ファイルに手作業で記述しましたが、コマンドラインから下記のコマンドを実行しても OKです。結果は同じになります。
1 |
$ bin/cake plugin load Search |
3.Model(Table)に検索処理を追加
Model(Table)にビヘイビアと検索条件の追加を行います。
/src/Model/Table/TestsTable.php
に下記の処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public function initialize(array $config) { : (既存の処理) : // ビヘイビア(friendsofcake/search)の追加 $this->addBehavior("Search.Search"); // 検索条件の追加 $this->searchManager() ->like("title",[ "before" => true, "after" => true ]); |
「ビヘイビアの追加」と「検索条件の追加」の処理を追加します。
「検索条件の追加」の箇所は実際に検索する条件に合わせて設定を変更する箇所です。
ここでは「title」という項目を「like検索」する設定になっています。また、「before」「after」を追加して、対象文字列の中の何処かに一致すればいい「中間一致検索」になる設定になっています。
最初の設置の際は、動作確認ができる最低限の項目にしておくことをオススメします。
また、「検索条件の追加」の部分を「initialize()」メソッドの中に書かずに、function()として独立して記述する方法もあります。
記述するファイルは、変わらず「/src/Model/Table/TestsTable.php」の中です。
1 2 3 4 5 6 7 8 9 10 11 |
// 検索条件の追加 public function searchManager() { $searchManager = $this->behaviors()->Search->searchManager(); $searchManager ->like("title",[ "before"=>true, "after"=>true ]); return $searchManager; } |
4.Controllerに検索処理を追加
Controllerに検索処理を追加します。
/src/Controller/TestsController.php
に下記の処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class TestsController extends AppController { // ページング設定の追加 public $paginate = [ "limit" => 100 ]; public function initialize() { parent::initialize(); // 検索処理のロードの追加 $this->loadComponent("Search.Prg", [ "actions" => ["index"] // ここで検索するアクションを配列で指定 ]); } public function index() { // Bakeしたときに生成された元の処理 // $tests = $this->paginate($this->Tests); // 上記の元の処理を下記に変更 $query = $this->Tests ->find("search",["search"=>$this->request->getQuery()]); $tests = $this->paginate($query); $this->set(compact("tests")); } |
「ページング設定の追加」は、設定内容の変更をしたい場合に追加します。
なくても動作しますので、最初の動作確認の段階ではなくても問題ありません。
「検索処理のロードの追加」では、検索処理を追加するアクションを指定します。
今回は「index」アクション内で検索処理を行いますのでそれを指定しています。
また、「index()」アクション内では、レコードを取得するクエリーに検索条件を含む「find()」句を追加します。
ちなみに、「initialize()」メソッド内の「検索処理のロードの追加」の「"actions" => ["index"]
」は、デフォルト設定は「"actions" => ["index","lookup"]
」となっています。
下記のように「actions」の部分をコメントにしても、「index」「lookup」アクション内であれば検索処理は動作します。(とは言え、明示しておくほうが無難ですが。)
1 2 3 4 |
// 検索処理のロードの追加 $this->loadComponent("Search.Prg", [ // "actions" => ["index"] // ここで検索するアクションを配列で指定 ]); |
ちなみに、「$this->loadComponent();」の処理は記述しないと検索できません。
5.Templateに検索条件のテキストボックスを追加
最後に、Templateに検索条件を入力するテキストボックスを追加します。
/src/Template/Tests/index.ctp
に下記の処理を追加します。
1 2 3 4 5 6 7 8 |
<div> <?php echo $this->Form->create(null, ["valueSources" => "query"]); echo $this->Form->input("title"); echo $this->Form->button(__("Search"), ["type" => "submit"]); echo $this->Form->end(); ?> </div> |
4行目は、検索対象となる項目を指定してください。
上記の設定であれば、検索条件のテキストボックスに入力した文字列は、検索結果のページにも表示されます。
古いサイトを参考にすると「$this->Form->create()」と書いてある場合もありますが、その記述だけでは、検索結果ページのテキストボックスに入力した文字列が編集されませんので注意をしてください。
1 2 3 4 5 |
// 間違い echo $this->Form->create(); // 正解! echo $this->Form->create(null, ["valueSources" => "query"]); |
もしくは、下記の設定でも OKです。
1 2 3 4 5 6 |
// 間違い echo $this->Form->create(); // 正解! echo $this->Form->create(); $this->Form->setValueSources("query"); // この行を追加する |
テキストボックスなどをカスタマイズしたい場合は、下記に Form Helperの使い方の記事を書いていますので、こちらを参考にしてください。
CakePHP3のForm Helperの使い方のまとめ
アンカーリンク付きのフォームタグを生成する方法
パソコンのブラウザではあまり気になりませんが、スマホで検索をした場合、ページの一番上に戻ってしまい、検索結果の一覧のところまで画面をスクロールさせるのが面倒、という場合がありました。
そんなときは、アンカーリンク(ページ内リンク)を設定しようと思いましたが、ちょっと悩んだところでもありましたのでここに追記しておきます。(2019.09.28 追記)
アンカーリンクを設定する方法は簡単です。
通常はリンク先を設定する「action」属性(フォームの POSTする先の URLを指定する箇所)に「#search」のようにアンカーリンク先を指定するだけです。
1 |
echo $this->Form->create(null, ["valueSources"=>"query","url"=>"#search"]); |
上記のように設定すると、下記のような HTMLが生成されます。
1 |
<form method="post" accept-charset="utf-8" role="form" action="#search"> |
これで検索を実行すると、検索処理が行われ、アンカーリンクを設定しているところに画面がスクロールして表示されます。
「"url"=>"#search"
」を設定すると、検索クエリーが処理されないのではないか、とも思っていましたが、全くそんな心配はいりませんでした。
ちなみに、アンカー側の記述は HTMLのタグとして下記のように記述します。
1 |
<a name="search"> </a> |
cakephp3の HTML Helperで記述する方法を調べてみましたが、よく分かりませんでした。
CakePHP3の検索プラグイン「friendsofcake/search」の導入方法のバリエーション
前の章では、検索プラグイン「friendsofcake/search」の基本的な導入方法を解説しました。
ですが、「friendsofcake/search」の導入方法は単一ではなく、いくつものバリエーションが存在しますので、それらの方法を解説します。
Model(Table)の記述を以前の記述方法で踏襲する
以前は、検索条件を「searchConfiguration()」の中に記述する方法がありました。
その方法を踏襲する場合は、下記のように記述することで実現できます。
/src/Model/Table/TestsTable.php
に下記の処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public function initialize(array $config) { : (既存の処理) : // ビヘイビアの追加(friendsofcake/search) $this->addBehavior("Search.Search"); // 検索条件の追加 $this->searchConfiguration(); } // 検索条件の追加 public function searchConfiguration() { $this->searchManager()->like("title",["before"=>true,"after"=>true]); } |
Controllerに追加する検索処理のバリエーション
Controllerに記述する検索処理は多様な記述の仕方があります。
各人で好みの記述方法があると思いますので、それに合わせた記述方法を試してみてください。
Controllerに追加する検索処理ですが、$queryの記述の方法を 2分割すると下記のような記述になります。
1 2 |
$filter = ["search"=>$this->request->getQuery()]; $query = $this->Tests->find("search", $filter); |
また、クエリ文字列(クエリストリング、URLパラメーター)を取得する方法は、CakePHP3.4で新しい方法が追加されていますので、CakePHP3.4以降を使っているのであれば、新しい方をオススメします。
1 2 3 4 5 6 7 8 9 |
// CakePHP3.4 以降 $filter = ["search"=>$this->request->getQuery()]; // もしくは // CakePHP3.4 以降 $filter = ["search"=>$this->request->getQueryParams()]; // CakePHP3.4 より前 $filter = ["search"=>$this->request->query]; |
また、テーブルの連携先(アソシエーション)の情報も取得したい場合は、「contain()句」を利用しますが、これも連結させるだけで OKです。
1 2 3 |
$query = $this->Tests ->find("search",["search"=>$this->request->getQuery()]) ->contain(["Users"]); |
検索プラグイン「friendsofcake/search」導入方法時にエラーが発生した!
記事の最初に「friendsofcake/search」の導入は簡単でした、と書きましたが、実はエラーが消えなくて延々と悩んでいました。
実は、CakePHP3.6以降では少し記述の方法が変更になったのですが、それを分かっておらず、古い記述の方法で書いていたためでした。
プラグインの実装の実験などをしている別の環境に、別の記述方法で導入を試してみたらあっさりと動いたため、「この違いはなんなんだ??」と調べていくと、バージョンの違いによって記述の仕方が違う、ということが分かりました。
そんなワケで、CakePHP3に関する記事はなるべく新しい記事を参考にしたほうがいいのかもしれませんね。(そのためには、記事には投稿日時が欠かせませんね。)
で、そんなこんなで発生したエラーの紹介です。
「Custom finder “search” expects search arguments to be nested under key “search” in find() options.」のエラー
「friendsofcake/search」を組み込んで動作させると、下記のエラーが発生しました。
Error: [Exception] Custom finder "search" expects search arguments to be nested under key "search" in find() options.
私は、TestController.phpの index()アクションの中の処理で下記のように書いていました。
1 2 3 |
$filter = $this->request->getQuery(); $query = $this->Tests->find("search", $filter)->contain(["Users"]); $bookmarks = $this->paginate($query); |
先に紹介した「$filter」の設定内容を見比べてもらうと分かるのですが、「$filter」に設定する方法が少し変わったようです。
1 2 3 4 5 |
// 正解 $filter = ["search"=>$this->request->getQuery()]; // 間違い $filter = $this->request->getQuery(); |
CakePHPのことをより分かってそうな方が書いているサイトだったのでそれを信じてしまっていましたが、分かったときには「バージョンが古かったんかぁーーいっ!!」という感じでした。
検索プラグイン「friendsofcake/search」のカスタマイズについて
この記事では、CakePHP3の検索プラグイン「friendsofcake/search」を設置して動作させるための基本的な解説を行いました。
記事が長くなりすぎるための実用的なカスタマイズに関しては下記の記事で改めて書いていますので、こちらを参考にしてください。
CakePHP3の検索プラグイン「friendsofcake/search」の様々な検索の仕方の実装方法
CakePHP3のfriendsofcake/searchでブックマークチュートリアルのタグ検索を実装
CakePHP3のfriendsofcake/searchでツリーカテゴリーの子階層も含めて検索する方法
CakePHP3の関連記事
CakePHP4のCSS、JavaScript、画像のブラウザへのキャッシュをコントロールするCakePHP3でレコードを保存(追加、更新、Insert、Update)する複数の方法を紹介
CakePHP3でモデルなしフォームからCSVをアップロードしレコードを更新する方法解説
CakePHP3でPHP Simple HTML DOM Parserを使ってスクレイピングする方法
CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も
CakePHP3の1対多での連携を中間テーブルを使った多対多の連携に変更するときの手順
CakePHP3でデフォルトのソート条件を設定してユーザの選択肢たソート条件を有効にする方法
CakePHP3で Ajaxを使う方法の解説。3.6以降対応。Successとthenの両方を解説。
CakePHP3でパンくずの指定は HTMLヘルパーを使って指定する方法を解説
CakePHP3にOGPをfetch、asignを利用してテンプレートごとに指定する方法を解説
その他の「CakePHP3」に関する記事一覧
GoogleAdwords
GoogleAdwords
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!
関連記事
-
CakePHP 2.x系 Viewでのコメントの記述方法など
CakePHPにおいて View、ctpファイルでコメントを記述する方法を解説。
-
CakePHP 2.3 Search Pluginで検索処理 その5入力項目に複数項目入力した場合の AND検索、OR検索
CakePHPの検索プラグイン Search Pluginの検索処理の中で複数項目を入力した場合の AND検索、OR検索についての解説です。
-
CakePHP 2.3 Search Pluginで検索処理 その1設置方法
CakePHPの検索プラグイン Search Pluginの設置方法と基本的な検索処理の解説です。
-
CakePHP4 のコマンドプログラムからコンポーネントを読み込む方法解説
CakePHP4でコマンドプログラムからコンポーネントを呼び出す方法を解説。コントローラーから呼び出すときと大差はないが、use句でコンポーネントを指定する事がポイント。
-
CakePHP3でモデルなしフォームからCSVをアップロードしレコードを更新する方法解説
CakePHP3でCSVファイルをアップロードしレコードを追加、更新する処理の作成方法の解説。モデルとは直接関連しないフォームからCSVファイルをアップロードするため汎用的に使用可能。
-
CakePHP 2.3 コマンドラインからPHPのシェル実行の方法解説
CakePHP 2.3でコマンドラインから CakePHPで記述した処理を実行する方法を解説します。
-
CakePHP3のfriendsofcake/searchでブックマークチュートリアルのタグ検索を実装
CakePHP3のCookbookにあるブックマークチュートリアル。ここで紹介されているタグで検索する処理を検索プラグイン「friendsofcake/search」で実現する方法を解説しました。
-
CakePHP4のクリエビルダーを使用してOR条件をAND条件でつなぐSQL文を作る方法
CakePHP4のクリエビルダーを使って複数のOR条件をANDでつなぐSQL文を作成する方法を解説。OR条件を記述したwhere句を2つつなげて記述する。
-
CakePHP3、CakePHP4のdatetime型カラムの日時の扱い。秒まで表示する方法
CakePHP3の日時カラムで秒まで扱う場合はdate()、strtotime()関数ではうまくいかない。CakePHP3であらかじめ用意された「i18nFormat()」を使用する。
-
CakePHP3の1対多での連携を中間テーブルを使った多対多の連携に変更するときの手順
CakePHP3で「1対多」の連携を中間テーブルを利用した「多対多」の連携に変更するときの手順のまとめ。中間テーブルの設定やModelの変更などを間違いやすい箇所を指摘しながらの解説。