k01ken’s b10g

He110 W0r1d!

CakePHP3のクエリービルダーで詰まったところ

開発環境は、Windows 10 Pro(64bit) + PHP 7.2.12 + CakePHP 3.6.13。

SQL文を直接書く時は簡単なんですけど、それをクエリービルダーをやる場合に、詰まってしまったポイントを書いておきます。


■クエリービルダーでselect句を使う際のカラム名について
クエリービルダーでitemsテーブルから情報を取得する際に、

<?php
$this->Items->find()
?>

と書くと、生成されるSQL文では、select句にて、各カラムの名前を、『頭文字が大文字のテーブル名__カラム名』というエイリアスにas句を使って自動的に変更しています。
例えば、itemsテーブルに、priceというカラムがあれば、『Items__price』という名前に自動的に変更しています。

そして、テンプレート側で取得結果を表示する場合は、
1.カラム名が頭文字が大文字のテーブル名__カラム名
 (例: Items__price
2.カラム名
 (例: price
のどちらかに、as句で変更していると、foreachなどでレコード1つ分を取得した際に、$item->カラム名(例えば、$item->price)のやり方で問題なく読み込んで表示しますが、それ以外の場合は、その名称で、指定しないといけませんので、ちょっと面倒。

select文でのカラム名の変更の方法は、itemsテーブルにて、Items__priceカラムをpriceカラムに変更したければ、

<?php
$this->Items->find()->select(['price' => 'Items__price']);
?>

とするだけで良いです。


■タイトル、記事内容、タグの中に特定のキーワードがあれば、結果として返す場合のクエリービルダーの例
SQL関数であるconcatでタイトルと記事内容とタグを結合したものを、LIKE句を使って、検索することにします。

<?php

$query = $this->Articles->find();
$concat = $query->func()->concat(['title' => 'identifier', 'article' => 'identifier','article_tag' => 'identifier']);
$subquery = $query->select(['combine_string' => $concat])->select($this->Articles);

$q = $this->Articles->select(['id' => 'Articles__id', 'title' => 'Articles__title', 'article' => 'Articles__article', 'article_tag' => 'Articles__article_tag'])->from(["result" => $subquery])->where(['AND' => [['result.combine_string LIKE' => '%キーワード1%'], ['result.combine_string LIKE' => '%キーワード2%']])->order(['result.id' => 'DESC']);

$this->set('result', $this->paginate($q));
?>

参考リンク
CONCAT:文字列を結合する
CakePHP3.x ORMでFrom句に仮想テーブルを追加する方法 - Qiita
クエリービルダー - 3.7