[CakePHP4]クエリビルダーのselect句指定が超面倒と思った時の対処法
CakePHP4でデータ取得する際にクエリビルダーを使用してデータ取得するのですが、クエリビルダーのselectメソッドでcolumn指定してしまうと、必要なcolumn全て記述するのが超面倒です。
ちなみにselectAllExcept()がありますが、こちらは指定したもの以外をselect句に自動でセットしてくれる便利なメソッドではあるのですが、指定したものだけを取得したい場合は使えません。
色々試してみる
selectに何も指定しない
selectに何も指定しない場合は、CakePHPが自動的にすべてのカラムを指定して取得してくれます。
$articles = $this->Articles->find()
->contain([
'EyecatchImage',
'Categories'
])
->limit(10)
->orderDesc('publiced');
//生成されたSQL
SELECT
Articles.id AS Articles__id,
Articles.title AS Articles__title,
Articles.body AS Articles__body,
Articles.publiced AS Articles__publiced,
Articles.created AS Articles__created,
Articles.modified AS Articles__modified,
EyecatchImage.id AS EyecatchImage__id,
EyecatchImage.name AS EyecatchImage__name,
EyecatchImage.file_name AS EyecatchImage__file_name,
EyecatchImage.created AS EyecatchImage__created,
EyecatchImage.modified AS EyecatchImage__modified
FROM
articles Articles
LEFT JOIN images EyecatchImage ON EyecatchImage.id = (Articles.eyecatch_image_id)
ORDER BY
publiced DESC
LIMIT
10
selectに任意の項目を指定する
つぎにselectに任意の項目を指定します。当たり前ですが任意の項目なので指定したものだけを取得します。
$articles = $this->Articles->find()
->select([
'Articles.title'
])
->contain([
'EyecatchImage',
'Categories'
])
->limit(10)
->orderDesc('publiced');
// 生成されたSQL
SELECT
Articles.title AS Articles__title
FROM
articles Articles
LEFT JOIN images EyecatchImage ON EyecatchImage.id = (Articles.eyecatch_image_id)
ORDER BY
publiced DESC
LIMIT
10
selectに指定するものが少なければ問題ないのですが、10個20個と指定しないといけない、JOINするものはすべてのカラムを取得したい場合などは、どのカラムが必要なのか調べないといけないため面倒になってきます。
select指定してもまとめて取ってくれる方法があった
公式サイトを読んでいると、select指定しても他のカラムもまとめて取ってくれる方法が紹介されていました。
(今まで全然気づかなかった)
selectにテーブルクラスを渡してあげます。
$articles = $this->Articles->find()
->select([
'test' => 'Articles.title'
])
->select($this->Articles)
->contain([
'EyecatchImage',
'Categories'
])
->limit(10)
->orderDesc('publiced');
// 生成されたSQL
SELECT
Articles.title AS test,
Articles.id AS Articles__id,
Articles.title AS Articles__title,
Articles.body AS Articles__body,
Articles.publiced AS Articles__publiced,
Articles.created AS Articles__created,
Articles.modified AS Articles__modified
FROM
articles Articles
LEFT JOIN images EyecatchImage ON EyecatchImage.id = (Articles.eyecatch_image_id)
ORDER BY
publiced DESC
LIMIT
10
アソシエーション(join)をしているテーブルのカラム取得したい場合は、下記のようにします。
$articles = $this->Articles->find()
->select([
'test' => 'Articles.title'
])
->select($this->Articles)
->select($this->Articles->EyecatchImage)
->contain([
'EyecatchImage',
'Categories'
])
->limit(10)
->orderDesc('publiced');
// 発行されたSQL
SELECT
Articles.title AS test,
Articles.id AS Articles__id,
Articles.title AS Articles__title,
Articles.body AS Articles__body,
Articles.publiced AS Articles__publiced,
Articles.created AS Articles__created,
Articles.modified AS Articles__modified,
EyecatchImage.id AS EyecatchImage__id,
EyecatchImage.name AS EyecatchImage__name,
EyecatchImage.file_name AS EyecatchImage__file_name,
EyecatchImage.created AS EyecatchImage__created,
EyecatchImage.modified AS EyecatchImage__modified
FROM
articles Articles
LEFT JOIN images EyecatchImage ON EyecatchImage.id = (Articles.eyecatch_image_id)
ORDER BY
publiced DESC
LIMIT
10
このように任意もカラム指定とカラムを全てを取得することができます。
やり方は公式サイトにも記載されています。
select($fields) を呼んで、なおもテーブルのすべてのフィールドを選択したいなら、 次の方法でテーブルインスタンスを select() に渡すことができます。
// 計算された slug フィールドを含む、 articles テーブルのすべてのフィールドを取得
$query = $articlesTable->find();
$query
->select(['slug' => $query->func()->concat(['title' => 'identifier', '-', 'id' => 'identifier'])])
->select($articlesTable); // articles のすべてのフィールドを選択する
さいごに
今回紹介した方法は公式サイトに普通に紹介されていました。
コメント
コメントを残す