Cakephp PHP WEB開発

【Cakephp4】belongsToMany先のcheckbox複数選択要素を保存する方法

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

Cakephp4 にて、belongsToMany アソシエート先の複数選択要素を保存する方法です。
ありがちな例として、複数選択可のチェックボックスを用います。

前提

users テーブルがアソシエート元

animals テーブルが belongsToMany先

テーブルモデル上でアソシエートの設定はされているものとする

Cakephp4: checkboxで複数選択要素フォーム

// テンプレート内にて
<?= $this->Form->control('animals._ids', [
    'type' => 'select',
    'multiple' => 'checkbox',
    'options' => $animals, // 動物リストが代入されている想定
    'templates' => [
        'checkboxWrapper' => '{{label}}',
        'nestingLabel' => '{{hidden}}<label{{attrs}} class="col-md-3">{{input}} {{text}}</label>',
    ],
]) ?>

テンプレートにて、form ヘルパーでフォームを作成し、フォームの名前が「アソシエート先テーブル名 . _ids」となっている箇所が肝です。
こうすることで、複数選択要素を指定し、 newEntity()  生成時によしなに同時保存する形にしてくれます。

その後は、単体モデルを保存するように save() すればよいだけです。

Cakephp4: POSTリクエスト後の保存

// コントローラー内にて
$entity = $this->Users->newEntity($data);
if ($entity->getErrors()) {
    $this->Flash->error('修正が必要な項目があります。');

    return;
}
// アソシエート設定していれば単体モデルを保存するように振る舞うだけでアソシエート先も保存してくれる
if (!$this->Users->save($entity)) {
    throw new \Exception('処理に失敗しました。お手数ですが、再度処理をお願いいたします。');
}

ドキュメントでは newEntity() 時に associated プロパティを設定していますが、特になくても問題ありません。
が、別途バリデートを走らせたい場合などは明記する、もしくは関連データを一緒に保存する目的で宣言しておくのはコード的に「全然あり」だと思います。(後で自分が読むとき、他の人が読む時に関連モデルが明記されている方が理解しやすいので。)

-Cakephp, PHP, WEB開発
-