我试图让以下工作:
我有一个像以下的实体:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;
/**
* Contact
*
* @ORM\Table()
* @ORM\Entity()
*/
class Contact
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\ServiceClient", inversedBy="contacts")
* @ORM\JoinColumn(name="service_client", referencedColumnName="service_client")
*
* @JMS\Type("AppBundle\Entity\ServiceClient")
* @JMS\SerializedName("serviceClient")
*/
private $serviceClient;
}
我通过HTTP请求发送以下JSON(帖子,它是新的联系人,没有ID):
{
"name": "Lorem Ipsum",
"serviceClient": {"service_client": "ipsum"}
}
我期望JMS Serializer能够解析这种关系,并让我像这样坚持Contact对象:
<?php
$contact = $this->get('serializer')->deserialize(
$request->getContent(),
Contact::class, 'json'
);
$this->em->persist($contact);
$this->em->flush();
事实上我已经开始工作了(我发誓它正在运作)但是现在它给了我以下错误:
通过这种关系找到了一个新的实体 &#39;的appbundle \实体\联系#serviceClient&#39;没有配置 实体的级联持久化操作: 的appbundle \实体\ ServiceClient @ 000000006fafb93e00007f122bd10320。至 解决此问题:显式调用EntityManager#persist()on 这个未知的实体或配置级联持久存在此关联 映射例如@ManyToOne(..,cascade = {\&#34; persist \&#34;})。如果你 无法找出导致问题实施的实体 &#39;的appbundle \实体\ ServiceClient #__的toString()&#39;得到一个线索。&#34;
所以它试图坚持实体...我不想要的东西,因为实体已经存在。我只想要Doctrine来放置引用,即外键。
编辑:它似乎是构造函数,如果我将其设置为doctrine_object_constructor
它就像魔法一样,我不理解的是它为什么停止工作第一名。
任何人都可以分享任何想法或更清洁的方式来做我做的事情吗?
jms_serializer.object_constructor:
alias: jms_serializer.doctrine_object_constructor
public: false
答案 0 :(得分:0)
当 Doctrine 无法将您的关系映射到数据库中的现有记录时会发生此问题,因此它将尝试使用JSON对象中的数据创建一个新记录。
在您的情况下,JSON对象: {“service_client”:“ipsum”} 无法映射到现有的 ServiceClient 实例。
这是因为默认的JMS对象构造函数调用 unserialize 函数(如果你定义了这个方法,将是你的Entity中的那个)来构造对象,这意味着这个对象将始终被 Doctrine 视为新对象(从未被持久化)。
通过 doctrine_object_constructor , JMS 将从 Doctrine 获取对象。该对象来自 Doctrine ,不仅具有您在实体中定义的属性和方法,还有关于它是否是现有属性的元数据,它是数据库中的相应行(所以 Doctrine < / strong>可以检测稍后对记录进行的更新并处理它,因此 Doctrine 可以避免不正确的持久性。
答案 1 :(得分:-1)
Doctrine将尝试使用反序列化中给出的ServiceClient实体的引用来保持Contact。在manyToOne定义级别的实体定义中,您需要添加:
@ORM \ ManyToOne(targetEntity =&#34; AppBundle \ Entity \ ServiceClient&#34;,inversedBy =&#34; contacts&#34;,cascade = {&#34; persist&#34;})