php - CakePHP:无法通过 belongsTo 关联子项将数据保存到父实体
问题描述
问题描述
我正在尝试配置 CakePHP 3.7 API 以儿童优先的方式保存关联数据。实体——为了举例,我们称它们为Users
和Persons
——它们的关系如下:
用户表.php
...
$this->belongsTo('Persons', [
'foreignKey' => 'person_id',
'joinType' => 'LEFT',
'className' => 'MyPlugin.Persons',
]);
...
PersonsTable.php
$this->hasOne('Users', [
'foreignKey' => 'person_id',
'className' => 'MyPlugin.Users'
]);
在各自的实体中,它们各自将彼此的属性可见性设置为true
。我想要做的是POST
路由/users/
(UsersController.php
)并让它也保存Persons
包含的对象。有效载荷是这样的:
{
"username": "foo",
"password": "bar",
"persons": {
"dob": "1982-07-03",
}
}
保存方法的相关部分如下,来自UsersController.php
:
if ($this->request->is('post') && !empty($this->request->getData())) {
$data = $this->request->getData();
$newEntity = $this->Users->newEntity($data, ['associated' => 'Persons']);
$savedEntity = $this->Users->save($newEntity);
...
错误
这会产生以下 SQL 错误。
PDOException:SQLSTATE [23502]:非空违规:7 错误:“person_id”列中的空值违反非空约束细节:失败行包含(1、null、foo、bar)
我知道这是因为 Cake 试图保存到Users
而不必person_id
满足外键约束。在我的应用程序域中,无法反转这种 FK 关系,因为我们需要向左的一对多关系(用户 -> 1 个人)。
id
我怀疑在有效负载的persons
对象中发送一个JSON
将允许它正确保存。但是,由于各种原因,这在运行时是不可能的。例如,这就是它在“保存数据”CakePHP Book 页面中的显示方式......
$data = [
'title' => 'First Post',
'user' => [
'id' => 1,
'username' => 'mark'
]
];
...
$article = $articles->newEntity($data, [
'associated' => ['Users']
]);
$articles->save($article);
我知道以下内容也可能按照xPfqHZ对类似问题的建议工作,Persons
可以保存到Users
,但与我正在尝试做的事情相比,它感觉不太合适,并且感觉好像有一种方法可以通过Users
.
if ($this->request->is('post') && !empty($this->request->getData())) {
$data = $this->request->getData();
$newEntity = $this->Users->Persons->newEntity($data, ['associated' => 'Persons']);
$savedEntity = $this->Users->Persons->save($newEntity);
...
工作
现在我相信这在 CakePHP 2.X 中曾经是可能的,正如ndm在一个类似问题上的回答中所说的那样,一个人试图通过实体在一个请求中保存belongsTo
关联实体及其父实体。hasOne
belongsTo
这是预期的行为,saveAssociated() 并不是只保存关联记录,它也会保存主记录,所以你应该只使用 saveAssociated(),不需要手动设置外键等,CakePHP 会做那是自动的。
控制器
public function create() { if ($this->request->is('post') && !empty($this->request->data)): $this->CandidatesProblemReport->create(); if ($this->CandidatesProblemReport->saveAssociated($this->request->data)): // ... endif; endif; }
但是,在文档中,我无法在实体继承的对象上找到或使用该saveAssociated()
方法。调用它会产生方法未找到错误。此方法似乎只存在于文档中详述的对象上。除非我遗漏了明显的东西,否则有没有办法使用它,或者它是否被它的兄弟方法在内部使用?Cake\ORM\Table
Users
Cake\ORM\Association
BelongsTo()
记录/倾倒实体
使用Cake\Log\Log::error($newEntity);
或die(var_dump($newEntity));
显示Users
水合到对象中的有效负载数据,但我没有看到Persons
附加的对象(见下文)。
object(MyPlugin\Model\Entity\User)[299]
public 'username' => string 'foo' (length=3)
public 'password' => string 'bar' (length=3)
public '[new]' => boolean true
public '[accessible]' =>
array (size=5)
'*' => boolean false
'person_id' => boolean true
'username' => boolean true
'password' => boolean true
'person' => boolean true
public '[dirty]' =>
array (size=2)
'username' => boolean true
'password' => boolean true
public '[original]' =>
array (size=0)
empty
public '[virtual]' =>
array (size=0)
empty
public '[hasErrors]' => boolean false
public '[errors]' =>
array (size=0)
empty
public '[invalid]' =>
array (size=0)
empty
public '[repository]' => string 'MyPlugin.Users' (length=17)
试图\Cake\Log\Log::error($savedEntity);
在日志文件中不显示任何内容。
save()
关联论点
我考虑的另一个解决方案是使用文档中所示的$options['associated]
of (摘录如下)。如下设置为true,错误仍然发生。save()
保存(Cake\Datasource\EntityInterface $entity,数组 $options [])
... associated:如果为 true,则只要为关联定义的属性标记为脏,它将保存在传递的 $entity 中找到的第一级关联实体。如果是数组,它将被解释为要保存的关联列表。通过将自定义选项设置为数组值,可以使用此键提供不同的选项来保存关联的表对象。如果为 false,则不会保存任何关联的记录。(默认:真)...
UsersController.php
:
if ($this->request->is('post') && !empty($this->request->getData())) {
$data = $this->request->getData();
$newEntity = $this->Users->newEntity($data, ['associated' => 'Persons']);
$savedEntity = $this->Users->save($newEntity, ['associated' => true]);
...
概括
如果不经历PersonsController.php
和利用它的关系,hasOne
我很难通过.Users
Persons
UsersController.php
如果我错过了任何重要信息,或者您有问题/需要更多信息,请询问!我可能错过了一些明显的东西,但我会很感激任何可能的建议/解决方案。
解决方案
正如@ndm 所指出的,错误在于发布的数据。根据文档的“保存数据:保存属于关联”页面:
保存 belongsTo 关联时,ORM 需要一个嵌套实体,该实体以单数、下划线版本的关联名称命名。
张贴的密钥persons
应该是person
. 同样,如果实体命名为PersonSnapshots
,则水合到实体中的有效负载中的相关键必须是person_snapshot
。
推荐阅读
- nfs - nfs-server 不会在只读挂载的根目录上启动
- php - 如果 $x = 100 + “25%” + “$40” 在 php 中 $x 的值是多少,为什么?
- angular - 在 Angular 6 中加载配置文件
- .net - 在 IdentityServer4 中保护客户端
- ssh - ssh 到远程服务器,带参数运行脚本
- php - 如何编辑
- javascript - 在运行 Mocha 测试之前等待路由和数据库初始化
- python - 如何在声明后访问 CVXPY 变量/参数
- javascript - 如何为长日期字符串增加轴下方的空间?
- sql - 具有多个配置文件的用户的 PostgreSQL 模型