CakePHP4の数値項目は「like %10%」の部分一致検索(find select)はできない
2024/08/10
CakePHP4で数値項目のlike句の部分一致検索はできない
CakePHPの数値項目に対しては、下記のように like句を使用した select文は実行できないようです。
SELECT * FROM users WHERE income like '%100%';
CakePHP4で数値項目のlike句の部分一致検索はできないことの実例
like句の部分一致検索用のサンプルテーブル
下記のようなテーブルがあったとします。
1 2 3 4 5 6 7 8 9 |
CREATE TABLE `users` ( `id` smallint(6) NOT NULL UNIQUE COMMENT 'ユーザID', `name` varchar(50) NOT NULL COMMENT '氏名', `income` int(11) DEFAULT NULL COMMENT '収入', `created` datetime NOT NULL DEFAULT now() COMMENT '登録日時', `modified` datetime NOT NULL DEFAULT now() COMMENT '更新日時', PRIMARY KEY (`id`), UNIQUE KEY `id_UNIQUE` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ユーザーテーブル'; |
このテーブルに対して、CakePHPのクリエビルダーを使用して、「name(varchar型)」と「income(int型)」に対して「like 句」を使用してレコード検索をしてみました。
「name(varchar型)」に対する like句の部分一致検索は問題ない
「name」のように文字型の場合は下記の記述方法で何も問題は発生しません。
「%」を囲む文字は「’(シングルクォート)」で囲っても、「”(ダブルクォート)」で囲っても問題はありません。
1 2 3 4 |
$conditions = [ "name like" => "%" . $this->request->getParam("name") . "%" ]; $this->Users->find()->where($conditions); |
「income(int型)」に対する like句の部分一致検索はエラーが発生する
対して、数値項目である「income」に対して「%」ワイルドカードを使用した部分一致検索をしようとするとエラーになります。
1 2 3 4 |
$conditions = [ "income like" => "%" . $this->request->getParam("income") . "%" ]; $this->Users->find()->where($conditions); |
上記を実行すると
「Cannot convert value of type string to integer」
というエラーが出ます。
「『income』は数値項目だけど、検索対象の文字列『%100%』は数値に変換できませんよ」というエラーです。
そんなエラーですので、「%」を囲む文字を「’(シングルクォート)」「”(ダブルクォート)」のどちらにしても同じエラーが出ます。
「(バッククォート)」を使用するとエラーは出ないが部分一致検索はできていない
ちなみに、
下記のように「(バッククォート)」を使用すると、エラーは出なくなりますが、「%」が機能しなくなり、完全一致でないと対象レコードを取得できなくなります。
1 2 3 4 |
$conditions = [ "income like" => `%` . $this->request->getParam("income") . `%` ]; $this->Users->find()->where($conditions); |
この「`(バッククォート)」で囲むと「%」が機能しなくなるのは、「income(int型)」だけでなく、「name(varchar型)」でも同様でした。
ちなみに、「like」演算子を使っていてもワイルドカードを使用しない下記のような記述方法であればエラーは発生しません。
当然ですね。入力された値を数値として処理できますので。
1 2 3 4 |
$conditions = [ "income like" => $this->request->getParam("income") ]; $this->Users->find()->where($conditions); |
ただ、ワイルドカードを使えないのであれば like検索をする必要性がないわけですが...
「income(int型)」に対する「_」を使用するパターンマッチングもエラーが発生する
like句での検索には、「_(アンダースコア、アンダーバー)」を使用したパターンマッチングもあります。
select * from users where income like "100_100";
「income(int型)」の項目に対しては、「_(アンダースコア、アンダーバー)」を利用したパターンマッチングもエラーが発生します。
1 2 3 4 |
$conditions = [ "income like" => "100_" . $this->request->getParam("income") ]; $this->Users->find()->where($conditions); |
「%」を使用した部分一致検索と同様に
「Cannot convert value of type string to integer」
というエラーです。
「_(アンダースコア)」は数値に変換できませんので、まぁ、同じエラーが出るだろうな、ということは予想できることですね。
※「name(varchar型)」の方は「_(アンダースコア)」を使用したパターンマッチングも問題なく実行できます。
「income(int型)」に対する部分一致検索の問題は SQLクリエービルダーの問題
今回紹介した CakePHP4において、数値型カラムに対して like句を使用した部分一致検索で発生するエラーの問題は、CakePHPの SQLのクリエービルダーの不具合によるもののようです。
下記のようにクリエビルダーを使わずに直接 SQLを実行する方法ではエラーは発生せず、想定したレコードが取得でることからも判断できます。
1 2 3 4 |
$connection = ConnectionManager::get('default'); $users = $connection ->execute("SELECT * FROM users WHERE income like '%100%'") ->fetchAll('assoc'); |
数値項目を like句を使用した部分一致検索をする場面は多くないと思いますが、どうしても「数値項目を部分一致検索したい!」という場合は上記のようにクリエビルダーを使用せずに直接 SQLを記述する方法が検討に入るのではないか、と思います。
その他の方法としては、int型をやめて varchar型にする、などでしょうか...
もし、こうすれば出来るよ、と言う方法があればご教授ください!
今回の参考サイトは下記になります。
CakePHP4 クリエービルダー
https://book.cakephp.org/4/ja/orm/query-builder.html
「シングルクォート」「ダブルクォート」「バッククォート」の違いについては、下記の記事などが参考になるかと思います。
記事自体は Linuxのコマンドに関する記事ですが、PHPでも基本的な扱いは同じです。
https://www.server-memo.net/shellscript/quart.html
CakePHP4の関連記事
CakePHP4系でJSONレスポンスの処理ではwithStringBodyを使う。3との違い解説CakePHP4、CakePHP5の「warning: DebugKit is disabling...」の対処方法
MySQL+CakePHPのdate型、datetime型項目は「2999-12-31」までしか扱えない
CakePHP4のFrozenDateで1ヵ月前、先月、今月1日、来月末の日付などを算出する方法
CakePHP4のcake cache clear_allでPermission deniedはパーミッションの変更が必要
CakePHP4のクリエビルダーを使用してOR条件をAND条件でつなぐSQL文を作る方法
CakePHP4のController内でViewテンプレート、レイアウトの変更設定を記述する方法
CakePHP4から外部のデータベースにアクセスする方法解説
CakePHP4の数値項目は「like %10%」の部分一致検索(find select)はできない
CakePHP4でロギングスコープやログレベルを使用してログを出し分ける方法を解説
その他の「CakePHP4」に関する記事一覧
GoogleAdwords
GoogleAdwords
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!
関連記事
-
-
CakePHP3の1対多での連携を中間テーブルを使った多対多の連携に変更するときの手順
CakePHP3で「1対多」の連携を中間テーブルを利用した「多対多」の連携に変更するときの手順のまとめ。中間テーブルの設定やModelの変更などを間違いやすい箇所を指摘しながらの解説。
-
-
CakePHP3でcomposerを利用してライブラリ・プラグインをインストールする方法
CakePHP3でcomposerを使ってパッケージ(ライブラリ、プラグイン)をインストールする方法の解説。PHPを使うのはCakePHP3が初めてというような方への使い方から解説。
-
-
CakePHP 2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法
CakePHPの検索プラグイン Search Pluginの検索処理の中で入力エリア一つで複数の項目を同時に検索する方法を解説。
-
-
CakePHP3でWarning Error: SplFileInfo::openFile()エラーが発生した場合の対処方法
CakePHP3のキャッシュファイルのパーミッションエラー Error: SplFileInfo::openFile()が発生した場合の対応方法解説。app.phpにキャッシュファイルのパーミッション設定を行い、既存のファイルは削除。
-
-
CakePHP4で公開側と管理側のデザインテンプレートを分ける方法・setLayout()
CakePHP4でデフォルトのレイアウトファイル「default.php」は管理側に使用し、これとは別のデザインを公開側のページに設定したい、を実装する方法を解説。
-
-
CakePHP4のフラッシュメッセージの表示場所、デザインを変更する方法を解説
CakePHP4のエラーメッセージ、完了メッセージなどを表示するフラッシュ処理の解説。Controller、レイアウトファイル、テンプレートファイルでそれぞれ処理を指定する。
-
-
CakePHP4の規約外のカラムをキーにアソシエーション(テーブル連結)する方法
CakePHPで規定外のカラム名のキーを指定してアソシエーション(テーブル連結)をする方法を解説。アソシエーション名によってはミスが発生しやすい点もあるので注意も必要。
-
-
CakePHP3でCookieを保存、呼び出し、削除の操作・CakePHP3.7対応
CakePHP3.7でCookieを保存、取り出し、削除する方法を解説。CakePHP3でのCookieの取り扱いはバージョンごとに変更されるため、環境に合わせた方法を探す必要がある。
-
-
CakePHP2の検索Plugin CakeDC/Searchで重複を省くgroup by(distinct)の実装方法
CakePHP2の検索プラグイン「CakeDC/Search」で、重複レコードを省くgroup by、distinctを使う方法についての解説。設定する場所はpaginatorの条件とするので、find()関数と同じ。
-
-
CakePHP3のデバッグキット(DebugKit)を強制的に有効、無効に変更する方法
CakePHP3に付属しているデバッグのためのツール、デバッグキットを強制的に有効化、無効化する方法を解説。初期設定では開発環境としてありそうなドメインの場合のみ有効になるように設定されている。