CakePHP3のFormHelperで複数Tableを扱う際のバリデーションエラーの出し方

More than 3 years have passed since last update.


動作するコード

User, Companyテーブルに対してデータを保存したい場合のフォーム例となります。


controller

class PageController extends AppController

{
public function initialize()
{
$this->User = TableRegistry('User');
$this->Company = TableRegistry('Company');
}

public function index()
{
if ($this->request->is('post'))
{
// Validation実行
$user = $this->User->patchEntity(
$this->User->newEntity(),
$this->request->data['User']
);

// Validation実行
$company = $this->Company->patchEntity(
$this->Company->newEntity(),
$this->request->data['Company']
);

// Validation Errorが発生した場合
if ($user->errors() || $company->errors())
{
// Entityを配列に詰める
$entities = [
'User' => $user,
'Company' => $company
];

// エラーを保持したEntityをまとめてTemplateに送る
$this->set('entities', $entities);
return;
}

// データを保存
$this->User->save($user);
$this->Company->save($company);

// 保存が完了したらリダイレクト
return $this->redirect('page/index');
}

// Getの場合も空配列をsetしておく
$this->set('entities', []);
}
}



Template

<?= $this->Form->create($entities, ['type' => 'POST']) ?>

<?= $this->Form->input('User.name') ?>
<?= $this->Form->input('Company.name') ?>
<?= $this->Form->submit() ?>
<?= $this->Form->end() ?>


注意するポイント

$this->Form->create() の第一引数に、テーブル名のprefixをkeyとしたEntityの配列を渡してください。

こうしないと各テキストエリアにバリデーションエラーが表示されません。

公式ドキュメントに載っていない挙動であったため、数時間詰まりました。


動かないコード

$this->request->data['User'] = $user;

2.x系ではControllerで上記のようなコードを書いても動作しましたが、3.x系ではダメなので注意してください。