エス技研

WordPress、CakePHP、PHP、baserCMSなどの Web系システムを中心に情報を提供します!


CakePHP3の検索プラグイン「friendsofcake/search」の様々な検索の仕方の実装方法

      2019/07/22

CakePHP3の検索プラグイン「friendsofcake/search」の検索方法の実装方法

 

「friendsofcake/search」は CakePHP3で使われる検索処理のプラグイン

 
この記事では、CakePHP3の検索プラグイン「friendsofcake/search」を活用するために必要となる様々な検索の仕方についての実装方法を解説しています。
・部分一致検索
・以上、以下、より大きい、より小さい
・範囲指定での検索
・複数の項目の検索
などなど
 
「friendsofcake/search」の設置方法など、基本的な使い方については下記の記事を参考にしてください。
CakePHP3の検索プラグイン「friendsofcake/search」の設置方法・CakePHP3.6対応
 
また、この記事でも書ききれなかったブックマークチュートリアルのようなテーブル構造の検索に関しては下記に別記事を書いています。
CakePHP3のfriendsofcake/searchでブックマークチュートリアルのタグ検索を実装
 
また、CakePHP3のオフィシャルの Cookbookの中にある「『ブログチュートリアル・パート3』で『ツリーカテゴリーの作成(ツリービヘイビアの利用)』」で作成されるツリー構造のカテゴリを、自身のカテゴリを含む子階層のカテゴリをすべて対象として実施する検索を、検索プラグイン「friendsofcake/search」を利用して実装方法についての解説は、下記の記事を参考にしてください。
CakePHP3のfriendsofcake/searchでツリーカテゴリーの子階層も含めて検索する方法
 
 
ちなみに、「friendsofcake/search」の設置方法は、CakePHP3.6になったときに少し変わっていますので、CakePHP3.6がリリースされた 2018年4月14日以前に書かれた記事では動作しないものもあるように感じます。
「friendsofcake/search」の実装をするときは、記事が書かれた日付を確認しつつ参考にしたほうが良さそうです。
 
この記事は、CakePHP3.7で動作確認しながら書いています。
 
 

部分一致検索の場合「like」(設置方法の解説で紹介した基本形)

 
まずは、「friendsofcake/search」を利用する際の検索条件の設定方法についての基本形の確認です。
 
CakePHP3の検索プラグイン「friendsofcake/search」の設置方法・CakePHP3.6対応」で紹介した検索条件の記述内容は下記でした。(表示の都合上、改行せずに 1行に変更している箇所があります。)
 
/src/Model/Table/TestsTable.php
の「initialize()」メソッドに記載した内容です。
 

 
これは「where title like "%{入力文字列}%"」という SQL文になる検索条件の設定です。
 
「”before” => true」「”after” => true」は、「like」の条件として前方一致、後方一致、中間一致の条件を設定する「%」をどこに付けるかの設定です。
 
「”before” => true」「”after” => true」の設定は、記述しない場合はデフォルトの「”before” => false」「”after” => false」を設定したことになります。
 
「”before” => true」のみの場合は、
where title like "%{入力文字列}"
 
「”after” => true」のみの場合は、
where title like "{入力文字列}%"
 
日本語のイメージで「befoer」は「前方一致」と理解すると間違える原因になります。
「”before” => true」は「%」が「前につく」と理解する必要があります。
 
 


 
 

LIKE句による検索で複数のキーワードにヒットさせたい場合「multiValue」

 
LIKE句による検索で、複数のキーワードにヒットさせたい場合は以下のようになります。
 
例えば、検索キーワードを入力するエリアに「雨,学校,休み」と入力すると、「雨」「学校」「休み」のすべてのキーワードを含む文字列があるレコードのみを検索するような場合です。
 

 
「multiValue」を「true」にすることで、マルチワード検索が有効になります。
「multiValueSeparator」は、単語ごとを区切る文字列です。上記では「,(半角カンマ)」を区切り文字として指定しています。
「valueMode」は、複数の単語がある場合、複数の単語を「AND」か「OR」のいずれの条件で検索するか、を指定します。
 
ただし、区切り文字を半角スペースにする方法は分かりませんでした...
 
【注意】
ここで指定しているのは「valueMode」ですが、似たようなパラメータとして「fieldMode」と「valueMode」があります。
このあとで解説する、複数のカラムを対象として検索する際に指定するのは「fieldMode」です。お間違えのないように。
 
 

完全一致検索の場合「value」

 
前項の部分一致検索ではなく、完全一致検索をする場合は、下記の通り「value」を指定します。
 

 
ただ、前項の「like句」を利用する場合、「”before” => false」「”after” => false」を指定すると、結果的に完全一致検索になります。
(「value句」に「”before” => true」「”after” => true」を指定しても部分一致にはなりません。)
 
 

「value句」でも複数のキーワードにヒットさせる方法も「multiValue」

 
「value句」でも「like句」と同じく「,」などで区切って複数のキーワードを対象に検索をすることができます。
 

 
記述方法は「value句」でも「like句」とほぼ同じで「multiValue」「multiValueSeparator」を指定します。
 
「valueMode」はデフォルトで「OR」になっています。
「AND」にした場合、常に何もヒットしない状態になりますので、書く必要はなさそうです。
 
 

検索条件の項目を追加する場合

 
検索項目を複数にする場合の対応方法です。
 
例えば、検索する項目がこれまでの「title」の 1つから、「information_type(お知らせの区分)」も検索条件に加えたい、という場合は、下記のように「information_type」の項目をつなげて記述します。
 

 
「information_type」は、「1:お知らせ」「2:授業の情報」「3:部活の情報」と言った選択肢を selectボックスで選択する方法を想定しています。
また、検索に際してはコードで完全一致でヒットすることを想定しています。
 
検索項目を追加する場合は、その検索条件を入力する箇所も修正する必要があります。対象ファイルは「/src/Template/Tests/index.ctp」です。
 

 
「options」の設定など、Form Helperの使い方については、下記に記事を書いていますので参考にしてください。
CakePHP3のForm Helperの使い方のまとめ
 
 

検索条件を入力する inputの nameの値をテーブルのカラム名と違うものを設定する場合「field」

 
ここまでの解説では、検索するカラムが「title」なので、検索条件を入力するテキストボックスの指定も「$this->Form->input("title");」のようにしていました(テキストボックスの「name」の値も「title」でした)。
 
ですが、これでは「テーブルのカラム名がバレバレやん!カラム名と違う値をつけたい!」という場合もあるでしょう。
その方法は以下のとおりです。
 
「/src/Template/Tests/index.ctp」は、下記の 4行目のように「title」を「search1」に変更します。
 

 
そして、Model(Table)の方は以下のように 4行目の「field句」を追加し、ここにテーブルのカラム名「title」を指定します。
 

 
4行目の「field句」の指定は、入力のテキストボックスの nameの値と検索対象となるテーブルのカラム名が一致していないときにそれを関連付けるために必要になります。
一致しているときにも書いても問題ありませんので、書いておくことを習慣づけていたほうが分かりやすいかもしれません。
 
また、4行目は下記のように記述することもできます。

 
 

containで設定したテーブルの連携先(アソシエーション)を検索する場合「field」

 
テーブルの連携先(アソシエーション)のテーブルの項目を検索対象とする場合も「field句」にテーブル名を含めて記述すれば OKです。

 
テーブルの連携先(アソシエーション)の情報も取得したい場合は、「CakePHP3の検索プラグイン「friendsofcake/search」の設置方法・CakePHP3.6対応」では解説していましたが、Controllerのクエリの条件に「contain()句」を利用して追加する必要があります。
 

 
 

1つのテキストボックスに入力した条件を複数のカラムを対象として検索する場合「field」

 
入力ボックスは 1つで、その 1つのテキストボックスに入力した文字列を複数のカラムを対象にして検索することもできます。
 
例えば、お知らせを検索する場合、1つの入力で「title(タイトル)」と「body(本文)」のカラムの両方を対象として検索する場合です。
 
「/src/Template/Tests/index.ctp」でのテキストボックは、前項と同じ様に「search1」を指定します。
 

 
そして、Model(Table)の方は以下のように 4行目の「field句」を追加します。
 

 
一つ前の項目の設定方法が理解できていれば、この方法はすんなり理解が進むでしょう。
4行目の「field句」で検索対象のカラムを指定しますが、この配列に指定するカラムを追加するだけです。
 
ちなみに、指定するカラムが 1つのときは、下記のように配列にしなくても動作します。
 

 
 

複数のカラムの検索を AND、ORの設定を変更する方法「fieldMode」

 
4行目に指定した「field句」の複数のカラムは、デフォルトでは「or」で検索をします。
いずれかのカラムに該当の情報があった場合にヒットします。
 
しかし、場合によっては、どちらにもある場合のみヒットさせたい場合もあると思いますが、その場合は下記のように「fieldMode句」を追加します。
 

 
「fieldMode句」を設定しないデフォルトでは「”fieldMode”=>”or”」が設定されている状態になっています。
 
【注意】
ここで指定しているのは「fieldMode」ですが、似たようなパラメータとして「fieldMode」と「valueMode」があります。
先に解説した『「雨,学校,休み」を「,」ごとの単語に区切って検索する...』というところで指定するのは「valueMode」です。お間違えのないように。
 
 


 
 

部分一致検索を行う場合のワイルドカードの設定も含めたオプション設定いろいろ

 
説明がやや前後しますが、「like」による検索はワイルドカードの使用も想定されています。
下記に追加した 6行目、7行目がそれにあたります。
 

 
追加した 6、7行目はデフォルトで設定されているワイルドカードの設定を明記したものです。(記述しない場合でもデフォルトでこの設定になっています。)
 
検索条件として入力する文字列に「*」「?」をワイルドカードとして使用できる、ということです。
「*」は「0文字以上の何かの文字」、「?」は「1文字の何かの文字」を表現します。
 
入力する文字列の「*」は、SQLの「%」に変換され、「?」は「_」に変換されることを意味しています。
 
デフォルトの設定が「*」「?」ですが、この設定を変更したいときに「wildcardAny」「wildcardOne」を指定します。(解説を書きながら、多分変更したいと思うことはないだろうな、と思っています...)
 
完全一致で検索する場合の「value句」の場合は、「wildcardAny」「wildcardOne」の設定はありません。この点も「value句」と「like句」の違いと言えます。
 
ちなみに、SQLのワイルドカードに関して詳しく知りたい方は下記を参照してみてください。
https://www.dbonline.jp/mysql/select/index7.html
 
 

部分一致検索を行う場合のワイルドカードの設定も含めたオプション設定をする別の記述方法

 
前項のワイルドカード設定も含めたオプション設定する記述方法ですが、下記のように記述する方法もあります。
 

 
この記述方法は、下記の「friendsofcake/search」のマニュアルに最初に書いてある記述方法で、この記述方法が本来の記述方法であろうと思います。
https://github.com/FriendsOfCake/search/tree/master/docs
 
ですが、この記事で解説している記述方法もマニュアルに書いてありまして、より短く記述するためのエイリアスとしての設定なのであろうと思います。
 
どちらの記述方法でも問題ありませんが、より短く記述する方法が用意されていますので、短い記述法を便利に利用するほうがいいんじゃないかと思います。
 
 

一つのテーブルに対して複数の検索条件を設定する場合「useCollection」

 
例えば、「Topics」というテーブルに対して、公開されているページから検索する場合と、管理画面側から検索する場合があり、それぞれで検索項目が違う、という場合があるでしょう。
そんな場合の設定方法の解説です。
 
記述する場所は Model(Table)の「initialize()」メソッドです。
 

 
複数の検索条件を設定する場合は、上記のように「useCollection()」句を追加します。
次の「useCollection()句」が出てくるまでの間に書かれたものが検索条件となります。
 
 
そして、「useCollection()句」で設定した検索条件は、それを使用する Controllerで指定します。
 
具体的には、下記の 7行目に追加した「collection」で指定します。
下記では「search_title」という名称の「useCollection()句」を指定しています。
 

 
ここでは、「useCollection()句」は複数の検索条件を設定する場合に使用する、と紹介していますが、「useCollection()句」は検索条件が 1つの場合でも設定しておくほうが無難です。
検索条件を追加する時点で「useCollection()句」を追加すると、デバッグなどで二度手間になる可能性があるためです。
 
 

Booleanの項目を対象として検索したい場合「boolean」

 
Booleanの項目を対象として検索したい場合の記述方法を解説します。
 
例えば、「deleted(削除フラグ)」を対象として、管理画面からは削除フラグがあるレコードだけを検索したい、という場合などを想定します。
 

 
Booleanの検索での「True/False」はそれぞれ以下の通りとなります。
「true」と判定される文字列は「1, true, ‘1’, ‘true’, ‘yes’, ‘on’」です。
「false」と判定される文字列は「0, false, ‘0’, ‘false’, ‘no’, ‘off’」です。
 
入力側のテンプレートではいずれかの値を設定しましょう。
 
また、Boolean検索をする場合は、対象となるカラムも Booleanである必要があります。
Booleanではないカラムを対象に Boolean句で検索しても何もヒットしません。
 
 

項目が nullか、否かをチェックしたい場合「exists」

 
検索対象の項目が nullか、否かをチェックしたい場合の記述方法を解説します。
 
例えば、「body(本文)」が nullか、否かを条件に検索する場合です。
 

 
「body(本文)」を対象に「1」で検索した場合は「nullじゃない」レコードがヒットします。
「0」で検索した場合は「nullである」レコードがヒットします。
 
「0」で検索した場合、「null」のレコードはヒットしますが、nullではない空のカラム(文字が入力されていないカラム)はヒットしません。
そのため、「exists()句」を使う場合は、未入力の場合は nullになることを確認しておく必要がありそうです。
 
 

「exists句」の検索対象を nullではない値にする場合「nullValue」

 
「exists句」のオプションで検索対象を nullではない値にすることもできます。
 

 
具体的には、上記のようにオプション「nullValue」を指定すると、「nullValue」に指定した「あ」が入っているレコードを「true」として検索対象とします。
 
実運用のシステムで「あ」という文字列を検索することはないでしょうけども、前項で解説した、「空のカラム(nullではなく入力がないカラム)」を対象に検索したい場合には下記のように指定します。
 

 
ただ、「exists()」句に複数の文字列を指定することはできないようで、「空のカラム」「null」のどちらかの場合にもヒットさせる、ということはできなさそうです。
 
ちなみに、「exists句」の特徴は「is NULL」「is not NULL」で検索する点にあります。
ですが、「nullValue」を設定すると、「=」「!=」で検索するようになりますので、「nullValue」を設定するくらいなら、「value句」で設定するほうがいいんじゃないかと思います。
 
 

以上(>=)、以下(<=)、より大きい(>)、より小さい(<)を指定したい場合「compare」

 
以上(>=)、以下(<=)、より大きい(>)、より小さい(<)による値の比較を行いたい場合は「compare()句」を使います。
 
例えば、対象とする「age(学年)」が指定してあるお知らせがあるとして、入力した数値以上の学年を対象としたものを検索する場合の記述になります。
 
Model(Table)の「initialize()」メソッド内の検索条件の追加を下記のように変更します。
 

 
「>=」「<=」「>」「<」は「operator」で指定をします。
 
 


 
 

「compare()句」を使って範囲指定、between演算子のように指定したい場合

 
例えば、「age(学年)」を検索する際、**~**学年の範囲で検索したい、という場合に使う検索方法です。
 
Model(Table)の「initialize()」メソッドは以下のようになります。
 

 
テンプレート「/src/Template/Tests/index.ctp」では下記のように「age_from」「age_to」を指定します。
 

 
テンプレートファイルに入力項目を 2つ作成し、入力項目に合わせて検索項目を「compare()句」で 2つ作成するだけです。簡単です
 
 
マニュアルには「mode」のデフォルトは「AND」となっていると書かれていますが、「OR」を指定しても「OR」にならないのがちょっと気になります...
設定方法が分かる方、教えてください!
 
 

検索条件に where句を追加したい場合

 
検索条件に SQLの where句の条件を追加したい場合は、下記のように Controllerに where句を追加します。
 
例えば、検索対象のレコードとして、「deleted(削除フラグ)」が「1」のものは削除済みのレコードのため、検索対象から常に除外したい、という場合などです。
 
/src/Controller/TestsController.php
が対象ファイルになります。
 

 
9行目のように、「find句」に「where句」を追加します。
 
この記述方法は、「friendsofcake/search」を使った検索処理とは関係なく、CakePHP3の一般的な where句の使い方ですので、特に違和感はないでしょう。
 
 

チェックボックスで検索をしたい場合「callback」

 
チェックボックスで検索をする場合はちょっとだけ煩雑で、「callback句」を使います。
 
先にも一度紹介した「information_type(お知らせの区分)」を検索条件に加える方法ですが、先に紹介した処理では selectリストで 1つを選択する方式でした。
 
今度は、「information_type(お知らせの区分)」をチェックボックスで複数選択できるようにします。
 
まず、テンプレートファイル「/src/Template/Tests/index.ctp」に下記の処理を追加します。
 

 
チェックボックスを設定する場合は「”type”=>”select”」「”multiple”=>”checkbox”」の 2つを指定します。
 
Model(Table)の「initialize()」メソッドは以下のようになります。
 

 
「callback句」使い、チェックボックスから送信されてきた入力値の配列を「where句 + IN」に取り込みクエリーを作成します。
 
 
また、テンプレートファイルの「"options"=>$informationTypes」で編集する「$informationTypes」は、定数などで配列として持っている場合は問題ないと思いますが、「information_types」というマスターテーブルを持っているような場合は、下記のように Controllerファイルの中で配列を生成するといいでしょう。
 
Controllerの最初のところで use句で「TableRegistry」を指定します。
 

 
処理を実行するアクション内で「information_types」のテーブルを読み込み値を配列で取得します。
 

 
ちなみに、「get("InformationTypes")」の部分は
get("InformationTypes")
get("informationTypes")
get("information_types")
のどれでも動作しました。(規約としては、サンプルソースのアッパーキャメルケースが正しいのでしょう。)
 
 

検索条件の入力をクリアするリセットボタンを設置したい場合

 
一般的な入力フォームでは、入力内容をリセットするためのリセットボタンは見かけなくなりましたが、検索条件については入力値をリセットして改めて検索したいというニーズは存在しています。
 
というわけで、リセットボタンについても解説します。
 
/src/Template/Tests/index.ctp
に下記の処理を追加します。
 

 
「friendsofcake/search」のマニュアルに記載されているリセットの方式は、上記の 6行目に追加したリンクです。
改めて、検索ページを呼び出すことで入力情報を削除する、というものです。
 
 

リセットボタンを検索されたときだけ表示したい場合「loadHelper」

 
前項の内容はわざわざ解説するほどのものではないですが、このリセットのリンクを、検索したときだけ表示する方法も用意されています。
 
/src/View/AppView.php
に、下記の「friendsofcake/searchの検索処理」を追加します。
 

 
追加する処理は 5行目です。
デフォルトの「AppView.php」には 2行目の「parent::initialize();」もありませんので、ない場合は 2行目も追加します。
 
 
/src/Template/Tests/index.ctp
には下記の処理を追加します。
 

 
テンプレートファイルは、6行目、8行目の検索があるときだけの分岐処理を追加します。
 
今回はリセットボタンの表示/非表示ですが、この処理を使うと、検索を実行したときだけ検索条件入力エリアを表示する、といったカスタマイズなども簡単にできるようになります。
 
 

CakePHP3の関連記事

CakePHP3でデフォルトのソート条件を設定してユーザの選択肢たソート条件を有効にする方法
CakePHP3で Ajaxを使う方法の解説。3.6以降対応。Successとthenの両方を解説。
CakePHP3でパンくずの指定は HTMLヘルパーを使って指定する方法を解説
CakePHP3にOGPをfetch、asignを利用してテンプレートごとに指定する方法を解説
CakePHP3のOGPはHTMLヘルパーの$this->Html->meta()を使って設定
CakePHP3でkeywords、DescriptionをHTMLヘルパーを使って設定する
CakePHP3で環境変数を設定して本番環境と開発環境を分けて処理をする場合
CakePHP3でCookieを保存、呼び出し、削除の操作・CakePHP3.7対応
CakePHP3でアソシエーション先のカラムでデータをソートして取得したい
CakePHP3のdatetime型カラムの日時の扱い。秒まで正しく表示する方法
 
その他の「CakePHP3」に関する記事一覧
 
 

 - CakePHP 2.x 3.x

GoogleAdwords

GoogleAdwords

最後までお読みいただきましてありがとうございます。
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

下記の空欄を埋めてください。 * Time limit is exhausted. Please reload CAPTCHA.

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

※入力いただいたコメントは管理者の承認後に掲載されます。

  関連記事

CakePHP3の検索プラグイン「friendsofcake/search」の設置方法・CakePHP3.6対応
CakePHP3の検索プラグイン「friendsofcake/search」の設置方法・CakePHP3.6対応

CakePHP3で検索を担うプラグイン「friendsofcake/search」の紹介。基本的な設置方法の紹介のほか、処理の記述方法のバリエーション、エラーの解説など。CakeDC/searchより導入は簡単!

CakePHP3にWYSIWYGエディタのCKEditor4を設置、カスタマイズ方法を解説
CakePHP3にWYSIWYGエディタのCKEditor4を設置、カスタマイズ方法を解説

WYSIWYGエディタであるCKEditor4をCDNを利用して簡単にCakePHP3に導入する方法とカスタマイズする方法を解説。CakePHP3にはページごとの振り分けを行うブロック化を利用する。

CakePHP 2.3でファイルをアップロード・その2 ファイル名を乱数で設定

CakePHPのアップロードするファイル名を乱数で変更しセキュリティを高める方法を解説。

CakePHP 2.3 主キー(ID)以外のキーで更新方法 updateAll

主キー(ID)以外のカラムをキーとして更新する方法、updateAllの使い方をサンプルを用いて解説します。

CakePHP3で他のテーブルのマスタテーブルからセレクトボックス(プルダウンリスト)を作る
CakePHP3で他のテーブルのマスタテーブルからセレクトボックス(プルダウンリスト)を作る

他のテーブルのマスタのレコードからプルダウンリストを作成し、選択できるようにするサンプルプログラムと解説。ORMの設定によりデータベースの値を取得し、配列を作成し optionsに与える。

CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合

アソシエーション(連携)している先のテーブルの項目で条件抽出する際の考え方と注意点をサンプルソースを用いて説明しています。

CakePHPのバリデーションを入力値・項目の条件によって変える方法を解説
CakePHPのバリデーションを入力値・項目の条件によって変える方法を解説

入力された値によってバリデーション(入力チェック)の内容を切り替える。その処理をCakePHPで実装する方法を解説。条件ごとに unset関数を使ってバリデーションを削除する、という方法を採る。

CakePHP3のメール送信の処理・テンプレート使用・添付ファイル送信も解説
CakePHP3のメール送信の処理・テンプレート使用・添付ファイル送信も解説

CakePHP3からメールを送信する方法解説。基本的な記述方法を基にして、テンプレートを使う方法、ファイルを添付する方法へと拡張しながら解説。

CakePHP3のOGPはHTMLヘルパーの$this->Html->meta()を使って設定
CakePHP3のOGPはHTMLヘルパーの$this->Html->meta()を使って設定

CakePHP3でOGPを設定する方法を解説。metaタグを編集するHTMLヘルパーを利用してOGPのタグを編集する。また、エレメントとして分割することでメンテナンス性も向上させる。

CakePHP3で保存前にバリデーション結果を取得する2つの方法
CakePHP3で保存前にバリデーション結果を取得する2つの方法

CakePHP3でデータベースに値を保存する前にバリデーションを行い、その結果によって処理を振り分ける方法について解説。「$topic->errors()」と「$topic->hasErrors()」の2つの方法がある。