使用继承序列化包含对象的Doctrine数组 [英] Serialize Doctrine array containing objects using inheritance

查看:112
本文介绍了使用继承序列化包含对象的Doctrine数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题



当序列化一系列的Doctrine功能时,集合仍将有2个项目,但项目为空。 >

背景



我有一些实体相互延伸 B 扩展 A C extends B 。在实体 Test 中我有一个数组,其对象类型为 B $ test 将在序列化时具有预期值(两个项目的集合)。



$ test 包含一个变量(数组) collection 数组中的一个项目的类型为$ code> B 和类型 C 之一。



$ sTest 将获取两个项目的集合,但项目为空。
这是 $ sTest 中的字符串在 $ test {collection:[[],[]]}



测试脚本:

  $ test = new Test(); 

$ b = new B();
$ b-> setToken('asdf');
$ b-> setName('asdf');

$ c = new C();
$ c-> setToken('asdf');
$ c-> setName('asdf');
$ c-> setDescription('asdf');

$ test-> addCollection($ b);
$ test-> addCollection($ c);

//序列化
$ serializer = $ this-> container-> get('serializer');
$ sTest = $ serializer-> serialize($ test,'json');

// Deserialize
$ deserializer = $ this-> container-> get('serializer');
$ dTest = $ deserializer-> deserialize($ sTest,'Acme\DemoBundle\Entity\Test','json');

$ em = $ this-> getDoctrine() - > getManager();

$ em-> merge($ dTest);
$ em-> flush();

A:

 code><?php 

命名空间Acme\DemoBundle\Entity;

使用Doctrine\ORM\Mapping作为ORM;
使用JMS\Serializer\Annotation作为JMS;
/ **
* @ ORM\Entity
* @ ORM\InheritanceType(JOINED)
* @ ORM\\DiscriminatorColumn(name =discr,type =string)
* @ ORM\DiscriminatorMap({a=Acme\DemoBundle\Entity\A,b=Acme\DemoBundle\Entity\B ,c=Acme\DemoBundle\Entity\C})
*
* @ JMS\ExclusionPolicy(无)
* @ JMS\Discriminator field =type,map = {
*a:Acme\DemoBundle\Entity\A,
*b:Acme\DemoBundle\Entity\ B,
*c:Acme\DemoBundle\Entity\C,*
*})
* /
class A {

/ **
* @ ORM\Column(type =integer)
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =AUTO )
* /
protected $ id;

/ **
* @ ORM\Column(type =string,length = 100)
* /
protected $ token;

public function setToken($ token){
$ this-> token = $ token;
}

/ **
* @ JMS\VirtualProperty
* @ JMS\SerializedName(type)
* /
public function getDiscr()
{
return'a';
}

}

B:

 <?php 

命名空间Acme\DemoBundle\Entity;

使用Doctrine\ORM\Mapping作为ORM;
使用JMS\Serializer\Annotation作为JMS;

/ **
* @ ORM\Entity
* @ JMS\ExclusionPolicy(无)
* /
class B extends A {

/ **
* @ ORM\Column(type =string,length = 100)
* /
protected $ name;

/ **
* @ ORM\ManyToOne(targetEntity =Acme\DemoBundle\Entity\Test,inversedBy =collection)
* @ORM \JoinColumn(name =TestId,referencedColumnName =id)
* /
private $ test;

public function setName($ name){
$ this-> name = $ name;
}

/ **
* @ JMS\VirtualProperty
* @ JMS\SerializedName(type)
* /
public function getDiscr(){
return'b';
}


/ **
*获取名称
*
* @return string
* /
public function getName()
{
return $ this-> name;
}

/ **
*获取id
*
* @return integer
* /
public function getId )
{
return $ this-> id;
}

/ **
*设置标记
*
* @param string $ token
* @return B
* /
public function setToken($ token)
{
$ this-> token = $ token;

return $ this;
}

/ **
*获取令牌
*
* @return string
* /
public function getToken )
{
return $ this-> token;
}

/ **
*设置测试
*
* @param \Acme\DemoBundle\Entity\Test $ test
* @return B
* /
public function setTest(\Acme\DemoBundle\Entity\Test $ test = null)
{
$ this- > test = $ test;

return $ this;
}

/ **
*获取测试
*
* @return \Acme\DemoBundle\Entity\Test
* /
public function getTest()
{
return $ this-> test;
}
}

C:

 <?php 

命名空间Acme\DemoBundle\Entity;

使用Doctrine\ORM\Mapping作为ORM;
使用JMS\Serializer\Annotation作为JMS;

/ **
* @ ORM\Entity
* @ JMS\ExclusionPolicy(无)
* /
class C extends B {

/ **
* @ ORM\Column(type =text)
* /
protected $ description;

public function setDescription($ description){
$ this-> description = $ description;
}

/ **
* @ JMS\VirtualProperty
* @ JMS\SerializedName(type)
* /
public function getDiscr(){
return'c';
}

}

测试:

 <?php 

命名空间Acme\DemoBundle\Entity;

使用Doctrine\ORM\Mapping作为ORM;
使用JMS\Serializer\Annotation作为JMS;

/ **
* @ ORM\Entity
* /
class Test {

/ **
* @ ORM\Column(type =integer)
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =AUTO)
* /
protected $ ID;

/ **
* @ ORM\OneToMany(targetEntity =Acme\DemoBundle\Entity\B,mappedBy =test,cascade = {all} )
* @ JMS\Type(ArrayCollection<'Acme\DemoBundle\Entity\B'>)
* /
private $ collection;


/ **
*构造函数
* /
public function __construct()
{
$ this-> collection = new \Doctrine\Common\Collections\ArrayCollection();
}

/ **
*获取id
*
* @return integer
* /
public function getId )
{
return $ this-> id;
}

/ **
*添加集合
*
* @param \Acme\DemoBundle\Entity\B $ collection
* @return测试
* /
public function addCollection(\Acme\DemoBundle\Entity\B $ collection)
{
$ this-> collection [] = $ collection;

return $ this;
}

/ **
*删除集合
*
* @param \Acme\DemoBundle\Entity\B $ collection
* /
public function removeCollection(\Acme\DemoBundle\Entity\B $ collection)
{
$ this-> collection-> removeElement($ collection );
}

/ **
*获取收藏
*
* @return \Doctrine\Common\Collections\Collection
* /
public function getCollection()
{
return $ this-> collection;
}
}


解决方案

不正确的注释Test :: $ collection



正如 NDM Test :: $ collection 的注释不正确,引用该类型时需要省略引号:

  diff --git a / src / Test.php b / src / Test.php 
index c0da0c3。 .a5ea94e 100644
--- a / src / Test.php
+++ b / src / Test.php
@@ -19,7 +19,7 @@ class Test {

/ **
* @ ORM\OneToMany(targetEntity =Acme\DemoBundle\Entity\B,mappedBy =test,cascade = {all} )
- * @ JMS\Type(ArrayCollection<'Acme\DemoBundle\Entity\B'>)
+ * @ JMS\Type(ArrayCollection&Acme \\ DemoBundle\Entity\B>)
* /
private $ collection;

有关参考,请参阅 http://jmsyst.com/libs/serializer/master/reference/annotations#type



A :: $ token B :: $ name

$ b的缺少注释
$ b

在修复 Test :: $ collection 的注释后尝试序列化导致抛出以下异常

  JMS\Serializer\Exception\RuntimeException:
您必须为Acme\DemoBundle\Entity\B :: $定义一个类型名称。

  JMS\Serializer\Exception\RuntimeException:
您必须为Acme\DemoBundle\Entity\A :: $ token定义一个类型。

A :: $ token

  diff --git a / src / A.php b / src / A.php 
index eb89b36..f806581 100644
--- a / src / A.php
+++ b / src / A.php
@@ -29,6 +29,7 @@ class一个{

/ **
* @ ORM\Column(type =string,length = 100)
+ * @ JMS\Type(string)
* /
protected $ token;

B :: $ name

  diff --git a / src / B.php b / src / B.php 
index 71a8b0b .. 7b448c6 100644
--- a / src / B.php
+++ b / src / B.php
@@ -13,6 +13,7 @@ class B extends A {

/ **
* @ ORM\Column(type =string,length = 100)
+ * @ JMS\Type(string)
* /
protected $ name;

解决问题,并从上面给出您的脚本, $ test 可以成功序列化为

  {
collection:[
{
type:b,
token:asdf,
name:asdf
},
{
:c,
token:asdf,
name:asdf,
description:asdf
}
]
}


Problem:

When serializing a collection of Doctrine enitities the collection will still have 2 items though the items are empty.

Background:

I have a few entities which extends each other B extends A and C extends B. In the entity Test I have an array with objects of the type B. $test will have the expected values (collection with two items) at the moment of serialization.

$test contains a variable (array) collection one of the items in the array is of the type B and one of type C.

$sTest will get the collection of two items though the items are empty. This is how the string in $sTest lookslike after the serialization of $test "{"collection":[[],[]]}"

Test script:

$test = new Test();

$b = new B();
$b->setToken('asdf');
$b->setName('asdf');

$c = new C();
$c->setToken('asdf');
$c->setName('asdf');
$c->setDescription('asdf');

$test->addCollection($b);
$test->addCollection($c);

//Serialize
$serializer = $this->container->get('serializer');
$sTest = $serializer->serialize($test, 'json');

//Deserialize
$deserializer = $this->container->get('serializer');
$dTest = $deserializer->deserialize($sTest, 'Acme\DemoBundle\Entity\Test', 'json');

$em = $this->getDoctrine()->getManager();

$em->merge($dTest);
$em->flush();

A:

<?php

namespace Acme\DemoBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;
/**
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({"a" = "Acme\DemoBundle\Entity\A", "b" = "Acme\DemoBundle\Entity\B", "c" = "Acme\DemoBundle\Entity\C"})
 * 
 * @JMS\ExclusionPolicy("None")
 * @JMS\Discriminator(field = "type", map = {
 *          "a": "Acme\DemoBundle\Entity\A",
 *          "b": "Acme\DemoBundle\Entity\B",
 *          "c": "Acme\DemoBundle\Entity\C", * 
 *  })
 */
class A {

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $token;

    public function setToken($token){
        $this->token = $token;
    }    

    /**
     * @JMS\VirtualProperty
     * @JMS\SerializedName("type")
     */
    public function getDiscr()
    {
        return 'a';
    }

}

B:

<?php

namespace Acme\DemoBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;

/**
 * @ORM\Entity
 * @JMS\ExclusionPolicy("None")
 */
class B extends A {

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $name;

    /**
     * @ORM\ManyToOne(targetEntity="Acme\DemoBundle\Entity\Test", inversedBy="collection")
     * @ORM\JoinColumn(name="TestId", referencedColumnName="id")
     */
    private $test;

    public function setName($name) {
        $this->name = $name;
    }

    /**
     * @JMS\VirtualProperty
     * @JMS\SerializedName("type")
     */
    public function getDiscr() {
        return 'b';
    }


    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set token
     *
     * @param string $token
     * @return B
     */
    public function setToken($token)
    {
        $this->token = $token;

        return $this;
    }

    /**
     * Get token
     *
     * @return string 
     */
    public function getToken()
    {
        return $this->token;
    }

    /**
     * Set test
     *
     * @param \Acme\DemoBundle\Entity\Test $test
     * @return B
     */
    public function setTest(\Acme\DemoBundle\Entity\Test $test = null)
    {
        $this->test = $test;

        return $this;
    }

    /**
     * Get test
     *
     * @return \Acme\DemoBundle\Entity\Test 
     */
    public function getTest()
    {
        return $this->test;
    }
}

C:

<?php

namespace Acme\DemoBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;

/**
 * @ORM\Entity
 * @JMS\ExclusionPolicy("None")
 */
class C extends B {

    /**
     * @ORM\Column(type="text")
     */
    protected $description;

    public function setDescription($description) {
        $this->description = $description;
    }

    /**
     * @JMS\VirtualProperty
     * @JMS\SerializedName("type")
     */
    public function getDiscr() {
        return 'c';
    }

}

Test:

<?php

namespace Acme\DemoBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;

/**
 * @ORM\Entity
 */
class Test {

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity="Acme\DemoBundle\Entity\B", mappedBy="test", cascade={"all"})
     * @JMS\Type("ArrayCollection<'Acme\DemoBundle\Entity\B'>")
     */
    private $collection;


    /**
     * Constructor
     */
    public function __construct()
    {
        $this->collection = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Add collection
     *
     * @param \Acme\DemoBundle\Entity\B $collection
     * @return Test
     */
    public function addCollection(\Acme\DemoBundle\Entity\B $collection)
    {
        $this->collection[] = $collection;

        return $this;
    }

    /**
     * Remove collection
     *
     * @param \Acme\DemoBundle\Entity\B $collection
     */
    public function removeCollection(\Acme\DemoBundle\Entity\B $collection)
    {
        $this->collection->removeElement($collection);
    }

    /**
     * Get collection
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getCollection()
    {
        return $this->collection;
    }
}

解决方案

Incorrect annotation for Test::$collection

As pointed out by NDM, the annotation for Test::$collection is not correct, you need to omit the quotes when referencing the type:

diff --git a/src/Test.php b/src/Test.php
index c0da0c3..a5ea94e 100644
--- a/src/Test.php
+++ b/src/Test.php
@@ -19,7 +19,7 @@ class Test {

     /**
      * @ORM\OneToMany(targetEntity="Acme\DemoBundle\Entity\B",     mappedBy="test", cascade={"all"})
-     * @JMS\Type("ArrayCollection<'Acme\DemoBundle\Entity\B'>")
+     * @JMS\Type("ArrayCollection<Acme\DemoBundle\Entity\B>")
      */
     private $collection;

For reference, see http://jmsyst.com/libs/serializer/master/reference/annotations#type.

Missing annotations for A::$token and B::$name

Attempting to serialize after fixing the annotation for Test::$collection results in the following exceptions being thrown

JMS\Serializer\Exception\RuntimeException: 
You must define a type for Acme\DemoBundle\Entity\B::$name.

and

JMS\Serializer\Exception\RuntimeException: 
You must define a type for Acme\DemoBundle\Entity\A::$token.

Adding the missing annotation for A::$token:

diff --git a/src/A.php b/src/A.php
index eb89b36..f806581 100644
--- a/src/A.php
+++ b/src/A.php
@@ -29,6 +29,7 @@ class A {

     /**
      * @ORM\Column(type="string", length=100)
+     * @JMS\Type("string")
      */
     protected $token;

and for B::$name:

diff --git a/src/B.php b/src/B.php
index 71a8b0b..7b448c6 100644
--- a/src/B.php
+++ b/src/B.php
@@ -13,6 +13,7 @@ class B extends A {

     /**
      * @ORM\Column(type="string", length=100)
+     * @JMS\Type("string")
      */
     protected $name;

solves the issue and given your script from above, $test can be successfully serialized to

{
  "collection":[
    {
      "type":"b",
      "token":"asdf",
      "name":"asdf"
    },
    {
      "type":"c",
      "token":"asdf",
      "name":"asdf",
      "description":"asdf"
    }
  ]
}

这篇关于使用继承序列化包含对象的Doctrine数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆