例として1つの注文 (Orders) に対して、複数のパッケージ (Packs) 、さらにその中に複数の商品 (Items) が入っている構造を考える。今回は一画面でこれらを一気に作成して保存までやってしまいたい
まずはEntityに対してassociationルールを設定する。今回はOrders と Packs, Packsと Itemsの間に hasMany
関係があるため親要素となるTableにそのルールを記述する。
OrdersTable.php
...(前略)
public function initialize(array $config)
{
$this->hasMany('Packs', [
'foreignKey' => 'order_id'
]);
}
...(後略)
PacksTable.php
...(前略)
public function initialize(array $config)
{
$this->hasMany('Items', [
'foreignKey' => 'pack_id'
]);
}
...(後略)
テンプレートは以下のように書く。 cake bake template order
で生成されたものをベースにするといい。子要素、孫要素の名前の後に .[数字]
を入れると数字ごとに関連づいて保存される。
Orders/add.php
<?= $this->Form->create($order) ?>
<?= $this->Form->control('name') ?>
<?= $this->Form->control('date') ?>
<?= $this->Form->control('packs.0.name') ?>
<?= $this->Form->control('packs.0.items.0.name') ?>
<?= $this->Form->control('packs.0.items.1.name') ?>
<?= $this->Form->control('packs.1.name') ?>
<?= $this->Form->control('packs.1.items.0.name') ?>
<?= $this->Form->control('packs.1.items.1.name') ?>
<?= $this->Form->control('packs.1.items.2.name') ?>
<?= $this->Form->end() ?>
add アクションの中でリクエストを表示するとこんな感じ
OrdersContoroller.php
function add() {
var_dump($this->request->getData());
}
/* 出力結果
[
"name" => "ほげほげ",
"date" => "2018-12-21",
"packs" => [
0 => [
"name" => "hogehoge",
"items" => [
0 => [
"name" => "ほげほげ"
],
1 => [
"name" => "ほげほげ"
]
]
],
1 => [
"name" => "hogehoge",
"items" => [
0 => [
"name" => "ほげほげ"
],
1 => [
"name" => "ほげほげ"
],
2 => [
"name" => "ほげほげ"
]
]
]
]
]
*/
保存するときもassociationルールを設定する必要があるので注意
OrdersController
$order = $this->Orders->newEntity();
$order = $this->Orders->patchEntity($order, $this->request->data, [
'associated' => [
'Packs' => [
'associated' => [
'Items'
]
]
]
]);
$this->Orders->save($order)
これで保存が完了する。
デフォルトのpatchEntityだと子要素までしか見てくれないみたいなので、
patchEntity に association ルールを書くと孫要素までEntityとして変換してくれる。
saveした段階でEntityになると勘違いしてsaveメソッドにassociationルールを書いて詰まったのでメモしておく