我目前正在使用CakePHP为我编写的一些票务逻辑提供一个基于crud的API。我遇到了一个问题,我试图更改一个belongsTo关联和新关联中的数据,但它没有持久化。
执行持久化的控制器如下所示:
<?php
class TasksController extends Cake\Controller\Controller
{
public function initialize()
{
parent::initialize();
}
public function edit(array $ids): void
{
$validationErrors = [];
$tasks = $this->Tasks->find('all')
->contain($this->setAssociations($query))
->where([$this->Model->getAlias().'.id IN' => $ids]);
foreach ($tasks as $id => $task) {
$this->Tasks->patchEntity($task, $this->request->getQuery()[$id], [
'associated' => ['Asset']
]);
}
if ($this->Tasks->saveMany($tasks)) {
$this->response = $this->response->withStatus(200);
} else {
// Handle errors
}
// Render json output for success / errors
$this->set($this->createViewVars(['entities' => $tasks], $validationErrors));
}
}
任务表中资产的关联如下所示:
<?php
class TasksTable extends Cake\ORM\Table
{
public function initialize(array $config)
{
$this->belongsTo('Asset', [
'className' => 'Assets',
'foreignKey' => 'asset_id',
'joinType' => 'LEFT'
]);
}
}
这些构建规则附加到资产表:
<?php
class AssetsTable extends Cake\ORM\Table
{
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['number', 'group_id'], 'The Number you selected is in use'));
$rules->add($rules->isUnique(['name', 'group_id'], 'The Name you selected is in use'));
}
}
我发送的请求的正文如下所示:
{
"421933": {
"description": "This task was edited by the api!",
"asset": {
"id": "138499",
"description": "This asset was edited by they api!",
"name": "105",
"number": "6"
}
}
}
基本上,名称105和编号6被标记为不唯一,因为它们已经在资产138499上设置为这些值。相反,查询尝试将名称105和编号6编辑到当前与任务实体(645163)关联的资产实体中,这将触发isUnquie构建规则失败。
您可以通过在上述控制器中的saveMany调用之前打印$tasks来查看这一点:
Array
(
[0] => App\Model\Entity\Task Object
(
[id] => 421933
[description] => This task was edited by the api!
.....
[asset] => App\Model\Entity\Asset Object
(
[id] => 645163
[name] => 105
[description] => This asset was edited by they api!
[number] => 6
....
)
)
)
将资产138499编辑为任务421933的关联似乎应该可以工作,因为看起来可以在CakePHP文档中以这种方式保存belongsTo关联,如下所示:
<?php
$data = [
'title' => 'First Post',
'user' => [
'id' => 1,
'username' => 'mark'
]
];
$articles = TableRegistry::getTableLocator()->get('Articles');
$article = $articles->newEntity($data, [
'associated' => ['Users']
]);
$articles->save($article);
是否可以在同一事务中关联belongsTo关联并编辑它?如果可以,我的请求或代码应该如何不同地构造?
谢谢你!
1条答案
按热度按时间ufj5ltwl1#
正如评论中所暗示的那样,您遇到了编组器的限制,对此还没有非常严格的解决方法(您可能希望打开一个问题over at GitHub,也许有人希望承担为这种类型的编组/保存添加支持的任务)。
书中的例子并不是最好的例子,实际上我个人会删除/更改它,它只在允许批量分配主键时才起作用(默认情况下烘焙实体不是这样),并且它也只在创建新记录时起作用,即当要保存的实体标记为“新”时。然而,这样做会引入各种各样的怪癖,例如,验证规则会将数据视为“创建”(新),应用程序规则会将实体视为“更新”(非新),但不会接收任何现有/原始数据,其他保存阶段回调也是如此,这会将审计等工作搞砸,基本上是需要新数据 * 和 * 原始数据的任何工作。
长话短说,即使你能让它像这个例子一样工作,你也会在后面引入其他的问题,所以现在最好忘记这个问题。我现在想到的唯一的解决方法是比较给定的资产主键,手动加载现有的资产实体,并在修补数据之前替换已经加载的实体。大致是这样的:
getQuery()
用法更改为getData()
,因为您似乎不太可能通过查询字符串传递该数据。*