Cakephp PHP WEB開発

【Cakephp2→4】updateAll使用時の別テーブル参照はCake4ではできない件

※本サイトはPR表記を含みます。

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

-Cakephp, PHP, WEB開発
-