serialize online json_encode ejemplo array php symfony doctrine2 jmsserializerbundle

php - online - Serialize Doctrine array que contiene objetos usando herencia



serialize php ejemplo (2)

Problema :

Al serializar una colección de entidades de Doctrine, la colección aún tendrá 2 elementos aunque los elementos estén vacíos.

Antecedentes :

Tengo algunas entidades que se extienden entre sí B extiende A y C extiende B En la Test entidad, tengo una matriz con objetos del tipo B $test tendrá los valores esperados (colección con dos elementos) en el momento de la serialización.

$test contiene una collection variable (matriz) uno de los elementos en la matriz es del tipo B y uno de tipo C

$sTest obtendrá la colección de dos elementos aunque los artículos estén vacíos. Así es como se ve la cadena en $sTest después de la serialización de $test "{"collection":[[],[]]}"

Secuencia de comandos de prueba:

$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();

UN:

<?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''; } }

SEGUNDO:

<?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; } }

DO:

<?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''; } }

Prueba:

<?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; } }


Anotación incorrecta para Test::$collection

Como señaló NDM , la anotación para Test::$collection no es correcta, debe omitir las comillas al hacer referencia al tipo:

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;

Para referencia, vea http://jmsyst.com/libs/serializer/master/reference/annotations#type .

Anotaciones faltantes para A::$token y B::$name

Intentando serializar después de corregir la anotación para resultados de la Test::$collection en las siguientes excepciones lanzadas

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

y

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

Agregar la anotación faltante para 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;

y para 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;

resuelve el problema y dado su guión desde arriba, $test se puede serializar con éxito para

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


Para un requisito algo diferente (JSON) he creado una entidad base e implementado el comportamiento de la siguiente manera:

function jsonSerialize() { $arr = get_object_vars($this); foreach ($arr as $key => $var) { unset($arr[$key]); if (method_exists($var, ''jsonSerialize'')) { $var = $var->jsonSerialize(); } elseif ( $var instanceof /DateTime) { $var = $var->format(''Y-m-d/TH:i:s/Z''); } $arr[strtolower(preg_replace(''/([a-z])([A-Z])/'', ''$1_$2'', $key))] = $var; } return $arr; }