[英]CakePHP 4 - saving associated data not working with 3 simple tables
我在 CakePHP 4 中有一个应用程序,但在保存相关模型数据时遇到问题。 我已经阅读了 Cake 文档中的保存关联数据,但目前还不清楚这是如何应用的,尤其是在我的用例中。
该应用程序有 3 个与此问题相关的表:
items
sizes
items_sizes_wanted
该应用程序允许用户请求服装项目( items
),并且输入/保存此类项目的表单具有不同尺寸( sizes
)的下拉列表。 每个尺寸都有一个唯一的 ID。 用户可以在保存项目时选择一种或多种尺寸。 items_sizes_wanted
表应该根据用户选择的大小保存一(或多)行,并带有相应的项目 ID。 例如,如果他们为 Item 999 保存了尺寸 2、3 和 4,则此表中将有 3 行:
size_id | item_id
--------|---------
2 | 999
3 | 999
4 | 999
代码已经烘焙,Table 类中的关联看起来没问题:
// src/Model/Table/ItemsSizesWantedTable.php
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('items_sizes_wanted');
$this->belongsTo('Items', [
'foreignKey' => 'item_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Sizes', [
'foreignKey' => 'size_id',
'joinType' => 'INNER',
]);
}
该项目的实体类看起来也不错:
// src/Model/Entity/Item.php
// @property \App\Model\Entity\ItemsSizesWanted[] $items_sizes_wanted
protected $_accessible = [
// ...
'items_sizes_wanted' => true,
// ...
];
在保存项目的表单( src/templates/Items/add.php
)中,我使用了表单助手并使用点符号命名它:
<?php
// Note that $sizes is an array of key/value pairs from the
// 'sizes' table.
?>
<?= $this->Form->control('items_sizes_wanted.size_id', ['options' => $sizes, 'multiple' => 'multiple']) ?>
在浏览器中呈现时,这会产生一个有效的数组语法名称。 <option>
内部呈现的都有有效的ID,即来自sizes
表的ID。
<select name="items_sizes_wanted[size_id]" multiple="multiple">
当我使用以下命令将数据保存在我的控制器( src/Controller/ItemsController.php
)中时:
public function add()
{
$item = $this->Items->newEmptyEntity();
if ($this->request->is('post')) {
$item = $this->Items->patchEntity($item, $this->request->getData());
// Edit: some of the entity properties are manually set at this point, e.g.
$item->item_status = 'Wanted';
if ($this->Items->save($item)) {
$this->Flash->success(__('Your item has been listed.'));
}
}
}
数据已正确保存到items
表和闪存成功消息“您的项目已列出”。 显示在浏览器中。
但是 - 没有数据写入items_sizes_wanted
。
我不确定这是为什么。 链接的文档没有具体说明应该如何使用表单助手,所以我假设我对该表单字段的语法是正确的,但它可能不是。
如果我在使用debug($item); die;
debug($item); die;
在控制器中它有'items_sizes_wanted' => [ ]
即使我使用表单选择了多个尺寸选项。
请有人帮忙,因为我不知道这里出了什么问题?
免责声明:我不太了解 CakePHP,但我想我要么知道解决方案,要么至少可以为您指明正确的方向。
你只得到一个选定的大小而不是多个的原因是因为生成的输入字段被命名为items_sizes_wanted[size_id]
但是,为了让 PHP 将多个值解析为一个数组,它们需要被命名为items_sizes_wanted[size_id][]
。 当请求参数以[]
结尾时,PHP 会正确地将所有请求属性解析为一个数组。
例如:这里是var_dump($_POST);
包含items_sizes_wanted[size_id][]=A&items_sizes_wanted[size_id][]=B&items_sizes_wanted[size_id][]=C
的 POST 正文的请求的
array (size=1)
'items_sizes_wanted' =>
array (size=1)
'size_id' =>
array (size=3)
0 => string 'A' (length=1)
1 => string 'B' (length=1)
2 => string 'C' (length=1)
将其与items_sizes_wanted[size_id]=A&items_sizes_wanted[size_id]=B&items_sizes_wanted[size_id]=C
的 POST 正文进行比较(注意每个末尾的空括号已被删除):
array (size=1)
'items_sizes_wanted' =>
array (size=1)
'size_id' => string 'C' (length=1)
这是我对 CakePHP 不太熟悉的部分。 我查看了CakePHP 的 FormHelper的代码,并且基于模板代码,我认为您需要将add.php
中的表单代码更改为如下所示(重新格式化以提高可读性):
<?php
// Note that $sizes is an array of key/value pairs from the
// 'sizes' table.
?>
<?=
$this->Form->control(
'items_sizes_wanted.size_id',
[
'options' => $sizes,
'multiple' => 'multiple'
'type' => 'selectMultiple'
]
)
?>
基于FormHelper 中的__call()
方法,你也可以这样写:
$this->Form->selectMultiple(
'items_sizes_wanted.size_id',
[
'options' => $sizes,
'multiple' => 'multiple'
]
);
但是,我不熟悉创建control($fieldName, $options)
和inputType($fieldName, $options)
之间的细微差别,因此它们可能会产生不同的输出。
我目前在 CakePHP 4.x 的一个项目中工作。 我的项目也有很多对很多的关联,它可以保存在表格中,但是 CakePHP 烘焙它与你的完全不同。 让我向您展示差异,也许它会有所帮助。
我会将我的实体、表格等的名称“翻译”为您问题中使用的名称,好吗?
首先,简要说明:在我的项目中,cake 没有为关系表烘焙模型(实体和表)。 关系表没有自己的模型,仅在ItemsTable
和WantedSizesTable
的initialize
方法中引用。 Item
和WantedSize
实体以及视图中也有细微的变化。
其次,您的实体名称不符合 Cake 的命名约定,这会导致很多问题。 这甚至可能是您现在所忍受的问题的原因。 我已经更改了一些名称以符合它们,但我建议您仔细阅读: https ://book.cakephp.org/4/en/intro/conventions.html。
第三个也是更重要的,让我们开始吧。
我的多对多关系 mySQL 表没有自己的表模型。 我的 SQL 确实有一个items_wanted_sizes
表,但 CakePHP 项目没有相应的模型,称为ItemsWantedSizesTable
或ItemsWantedSizes
。 它确实有ItemsTable
和WantedSizesTable
表以及Item
和WantedSize
实体,仅此而已。
让我们看看表模型。 关系 mySQL 表items_wanted_sizes
仅在 PHP 中两个表模型的表initialize
方法中引用,如下所示:
// ItemsTable.php
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('items');
$this->setDisplayField('item_name');
$this->setPrimaryKey('id');
// ...
// Other associations...
// ...
// The relational mysql table only shows here:
$this->belongsToMany('WantedSizes', [
'foreignKey' => 'item_id', // Item Id field from the relational table
'targetForeignKey' => 'wanted_size_id', // Size Id field from the relational table
'joinTable' => 'items_wanted_sizes',
]);
}
WantedSizesTable 上也会发生同样的情况:
// WantedSizesTable.php
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('wanted_sizes');
$this->setDisplayField('wanted_size_name');
$this->setPrimaryKey('id');
// ...
// Other associations...
// ...
// The relational mysql table only shows here:
$this->belongsToMany('Items', [
'foreignKey' => 'wanted_size_id', // Size Id fieldname from the relational table
'targetForeignKey' => 'item_id', // Item Id fieldname from the relational table
'joinTable' => 'items_wanted_sizes',
]);
}
关于实体模型,我也没有关系实体模型。 Item
和WantedSize
实体模型都相互引用,但与您的情况相反,它们不引用关系表(仅相互引用) :
// src/Model/Entity/Item.php
// @property \App\Model\Entity\WantedSize[] $wanted_sizes // NOT item_wanted_sizes
protected $_accessible = [
// ...
'wanted_sizes' => true, // NOT item_wanted_sizes
// ...
];
WantedSize 相同:
// src/Model/Entity/WantedSize.php
// @property \App\Model\Entity\Item[] $items // NOT item_wanted_sizes
protected $_accessible = [
// ...
'items' => true, // NOT item_wanted_sizes
// ...
];
现在我们看到了我们的模型,让我们跳转到添加(或编辑)操作视图。 正确设置关联后,我只需要这样做:
// src/templates/Items/add.php
echo $this->Form->control('wanted_sizes._ids', ['options' => $wantedSizes]);
我什至不需要告诉 FormHelper 这是一个多选,因为它在表格配置中。
生成的 HTML 与您的完全不同(就像上面回答的 404 一样):
<select name="wanted_sizes[_ids][]" multiple="multiple" id="wanted-sizes-ids">
<option value="1">Some wanted size...</option>
<!-- ... -->
</select>
这对我来说非常好,将数据保存在 mysql 的关系表中。
在 Cakephp4 中,要检查实体是否在修补后未显示关联数据的一件事是实体。 是 $_accessible 数组中的关联数据
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.