3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CakePHP3, CakePHP4 アソシエーションの条件を複数指定する!

3
Last updated at Posted at 2021-03-17

googleさんに multiple conditions columns join cakephp とかで調べても全然結果は出なかった。。。
以外と知られてない情報かもなという所で、共有と備忘録を兼ねて、残します。

他のモデルを結合 (JOIN) したい時に、複数のカラムを指定したい事があると思います。

例えば、同姓同名の別人を含むテーブルがあったとして

citizens

prefecture name birthyear
Tokyo 山田太郎 1990
Tokyo 名無し次郎 1988
Wakayama 山田太郎 1955

彼らからのコメントを保管するテーブルがあると

comments

prefecture name comment
Tokyo 山田太郎 わしはいいとおもう
Wakayama  山田太郎 いかんでしょ

(まあ、ビジネスキーをつけてれば何も問題ないのですが)、commentsテーブルの内容を select する時に、複数条件指定しないといけないわけです。

SQLだと、以下のような感じ

SELECT 
  citizens.prefecture, 
  citizens.name, 
  citizens.birthyaer, 
  comments.comment 
FROM comments 
LEFT JOIN citizens 
  ON citizens.prefecture = comments.prefecture
  AND citizens.name = comments.name

まあ、 JOIN の条件を AND で結んで複数指定すると。

まあ、こういった事をする際に、当然かの有名なCakePHPならいい感じに書けそうに思えるんですが、これがXXXXXな事に、デフォでは対応してないんですね。
https://api.cakephp.org/3.6/class-Cake.ORM.Association.HasOne.html#_foreignKey
foreignKey の引数はガッツリ string です。

つーわけで、なんかしらやり方がないかと思ったら、以下の書き方でどうにかなりました。
(Tableのアソシエーションです。これ分からないならまずドキュメント読んでください)

CommentsTable.php
()

use \Cake\Database\Expression\QueryExpression;



$this
  ->hasOne('Citizens', [ // まずここで一つだけ条件をセット
    'foreignKey' => 'name',
    'bindingKey' => 'name',
  ])
  ->setConditions([ // 上で指定した条件以外をココでセット。配列なので3つだろうが4つだろうがどんと来い
    new QueryExpression('Citizens.prefecture = 'Comments.prefecture)
  ]);
()

SQLログも確認しましたが、いい感じにONに対してANDを繋いでいたので、問題なさそう。
(QueryExpression以外だと、WHEREで指定してるっぽい)

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?