WEBOPIXEL

CakePHP4のQueryBuilderでいろいろな条件で検索してみよう

Posted: 2020.05.27 / Category: CakePHP 

CakePHP4のQueryBuilderでいろいろな条件で検索してみようということで使い方をまとめてみました。

Sponsored Link

テーブル構造

こんな感じのテーブルがあるとします。

$table = $this->table('posts');
$table->addColumn('title', 'string')
	->addColumn('description', 'text')
	->addColumn('body', 'text')
	->addColumn('published', 'boolean')
	->addColumn('created', 'datetime')
	->addColumn('modified', 'datetime')
	->create();

一覧を取得

すべてのデータを取得したいときはfindの引数にallを指定します。

$this->Posts->find('all');

引数のallはデフォルト値なので指定しないでも同じ結果になります。

$this->Posts->find();

キーワード完全一致

titleが指定したキーワードと一致したものを検索したいときはwhereで条件指定します。
引数は連想配列でkeyにカラム名、valueに検索ワードを指定します。

$this->Posts->find()->where(['title' => '検索ワード']);

キーワード部分一致

titleに指定したキーワードが含まれたものを検索したいときはLIKE検索を使います。
配列のkeyは「カラム名 LIKE」という形になります。
「%検索ワード」の場合は最後に「検索ワード」で終わる条件になり、「%検索ワード%」はどこかに「検索ワード」が含まれているかという条件です。

$this->Posts->find()->where(['title LIKE' => '%検索ワード%']);

複数条件を指定

titleのLIKE検索と、publishedがtrueの複数の条件で検索したい場合は、whereに配列で追加します。

$this->Posts->find()->where(['title LIKE' => '%検索ワード%', 'published' => true]);

andWhereで繋げても同じ結果になります。

$this->Posts->find()->where(['title LIKE' => '%検索ワード%'])->andWhere(['published' => true]);

複数条件(OR)検索

先ほどは複数の条件がマッチしたレコードだけ取得しました。
これをAND検索というのですが、今度はOR検索というのを試してみます。
例えばtitleにいずれかのキーワードが含むというのを条件にしてみましょう。

$this->Posts->find()
	->where([
		'OR' => [
			['title LIKE' => '%検索ワード1%'],
			['title LIKE' => '%検索ワード2%']
		]
	]);

指定日以降の検索

指定日以降を検索したい場合もwhereを使用します。
条件符号も付与することで指定した値以降のレコードを取得できます。
createが2020年4月28日以降を取得したい場合は次のようになります。

$this->Posts->find()->where(['created >' => '2020-04-28']);

指定した日の検索

createカラムはdatatime型ですが、日付で検索したい場合はDATEフォーマットに変換することでマッチさせることができます。
createが2020年4月28日のデータを取得したい場合は次のようになります。

$this->Posts->find()->where(['DATE(created)' => '2020-04-28']);

少し長いですがbetween使う方法もあります。

$this->Posts->find()->where(function($exp) {
	return $exp->between('created', '2020-04-28', '2020-04-29');
});

指定日から指定日までの範囲検索

全項目ですでに解説しましたが、指定日から指定日までの範囲検索するにはbetweenを使用します。
createが2020年4月28日から31日のデータを取得したい場合は次のようになります。

$this->Posts->find()->where(function($exp) {
	return $exp->between('created', '2020-04-28', '2020-05-01');
});

動的ファインダー

「findByカラム名」で検索することもできます。
例えばpublishedがtrueのものを取得したい場合、whereを使用すると下記のようになります。

$this->Posts->find()->where(['published' => false]);

動的ファインダーを使用すると下記のように短く書くことができます。

$this->Posts->findByPublished(true);

件数を指定

ここからは取得条件の設定になります。
3件だけなど、取得件数を指定する場合はlimitを使用します。

$this->Posts->find()->limit(3);

並び順を指定

デフォルトではプライマリキーの昇順で表示されますが、orderを指定することで、カラムの指定や並び方法を変更することができます。
createを降順で並び替えしたい場合は次のようになります。

$this->Posts->find()->order(['created' => 'desc']);

カラムを指定

カラム数が多い場合や情報量が多いカラムがある場合はselectで取得するカラムを指定することができます。

$this->Posts->find()->select(['id','title','created']);

リレーションの検索

テーブル同士で結合(リレーション)するということはよくあると思います。
モデルで設定しただけでは Userテーブルと繋げたい場合。

$this->Posts->find()->contain(['Users']);

2つのテーブルで同じ名前のカラムがある場合、使用する場合はカラム名も指定する必要があります。

$this->Posts->find()->contain(['Users'])->where(['Posts.created >' => '2020-04-20']);

belongsToManyでリレーション先で検索

よくあるPostsとTagsが多対多の関係でタグIDで検索したいときとか。

$this->Posts->find()
->matching(
	'Tags', function (Query $q) use ($id){
		return $q->where(['Tags.id' => $id]);
	}
);

この記事の動画(Youtube)版はこちら!