CakePHP:无法通过belongsTo关联的子对象将数据保存到父实体

时间:2019-05-31 18:50:10

标签: php cakephp associations cakephp-3.0 cakephp-2.0

问题描述

我正在尝试配置CakePHP 3.7 API以以子优先的方式保存关联的数据。为了举例说明,我们将实体称为UsersPersons-它们之间的关系如下:

UsersTable.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]:不为null违反:7错误:“ person_id”列中的null值违反了非null约束   详细信息:失败行包含(1,null,foo,bar)

我了解这是因为Cake试图保存到Users而没有person_id来满足外键约束。在我们的应用程序域中,无法扭转这种FK关系,因为我们需要向左的一对多关系(用户-> 1人)。

我怀疑在有效载荷id的{​​{1}}对象中发送persons可以使此正确保存。但是,由于各种原因,这在运行时是不可能的。例如,这就是"Saving Data" CakePHP Book page ...

中的显示方式
JSON

我知道以下类似问题也可能像suggested by xPfqHZ一样起作用,因为$data = [ 'title' => 'First Post', 'user' => [ 'id' => 1, 'username' => 'mark' ] ]; ... $article = $articles->newEntity($data, [ 'associated' => ['Users'] ]); $articles->save($article); 可以保存到Persons,但是与我尝试的内容相比,它不适合做,并且感觉好像有一种通过Users上的关联的方法。

Users

工作情况

现在,我相信这在CakePHP 2.X中曾经是可能的,如this answer by ndm所述,在一个类似的问题上,一个人试图保存 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); ... 关联实体及其父{{1 }}实体通过belongsTo实体的一个请求。

  

这是预期的行为,saveAssociated()并不意味着只保存相关记录,它也会保存主记录,因此您只应使用saveAssociated(),而无需手动设置外键,等等。 CakePHP将自动执行该操作。

     

控制器

hasOne

但是,我无法在文档中的belongsTo实体所继承的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()方法。调用它会产生方法未找到错误。如documentation中所述,此方法似乎仅存在于Cake\ORM\Table对象上。除非我没有遗漏,否则Users及其同级方法是否可以使用它?或者内部使用它?

记录/转储实体

使用Cake\ORM\AssociationBelongsTo()显示有效载荷的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) 关联参数

我考虑的另一种解决方案是使用documentation中所示的\Cake\Log\Log::error($savedEntity);的{​​{1}}(如下所示)。将此设置为true时,如下所示,仍然发生错误。

  

保存(Cake \ Datasource \ EntityInterface $ entity,数组$ options [])

     

... associated :如果为true,则只要为关联定义的属性标记为脏,它将保存在传递的$ entity中找到的第一级关联实体。如果是数组,它将被解释为要保存的关联列表。通过使自定义选项成为数组值,可以使用此键提供用于保存关联表对象的不同选项。如果为false,则不会保存任何关联记录。 (默认值:true)...

save()

$options['associated]

摘要

如果不经历save()并利用其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数据通过{{1 }}。

如果我错过了任何重要信息,或者您有其他疑问/需要其他信息,请询问!我可能错过了一些显而易见的事情,但我可能会提出任何建议/解决方案。

1 个答案:

答案 0 :(得分:0)

如@ndm所示,错误在于发布的数据中。按照文档的"Saving Data: Saving BelongsTo Associations"页:

  

在保存belongsTo关联时,ORM希望使用一个嵌套的实体,该关联实体的名称为关联名称的加下划线版本。

他们发布的密钥persons应该是person。同样,如果将实体命名为PersonSnapshots,则水合到实体中的有效载荷中的相关密钥将必须为person_snapshot