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()
は存在しますが、仕様が違うので注意したいところです。