
Cake2での updateAll() では 条件に別テーブルの参照ができていましたが、どうやら Cake4 ではできないようです。
例えば、以下のような Cake2 のコードを移行を考えた際、Cake4では、SQLを分割する方法が考えられます。
Cake2: updateAllに別テーブルのカラム条件が入っている場合
$conditions = [];
$conditions['id'] = $data['id'];
$conditions[] = ['OR' => [
['別テーブル.type' => 1],
['別テーブル.type' => 2],
]];
$this->updateAll(['name' => 'hogefuga'], $conditions);
Cake2 の場合、別テーブルを指定し、それを条件として利用できていました。が、Cake4 ではそのような書き方は許可されておらず、joinしようとすると、以下のようなエラーが発生します。
error
Aliases are being removed from conditions for UPDATE/DELETE queries, this can break references to joined tables.
対応方法としては、更新対象を別途 SELECT で取得して、それを UPDATE させる形で同様の結果が得られます。
最終手段としては直接SQLを書くということも考えられますが、Cakephp のお作法的に極力 ORM を利用します。
Cake4: updateAll()で別テーブルを条件にする際は別途SELECTで更新対象を取得する
use Cake\Utility\Hash;
// メソッド内
$results = $this->find()
->disableHydration()
->select(['id'])
->contain(['別テーブル'])
->where([
'id' => $data['id'],
'OR' => [
['別テーブル.type' => 1],
['別テーブル.type' => 2],
],
])
->toArray();
if (!empty($results)) {
$this->query()
->update()
->set(['name' => 'hogefuga'])
->where(['id IN' => Hash::extract($results, '{n}.id')])
->execute();
}
更新対象の ID 群を取得し、それを update() の IN句 として渡し、更新をかけることで結果的にCake2の updateAll() と同じになりました。
Cakephp4にも updateAll() は存在しますが、仕様が違うので注意したいところです。