2

J'utilise JMSSerializer - avec le constructeur Doctrine - afin de désérialiser un objet envoyé.comment faire pour qu'une propriété soit "fusionnée" ou initialisée lors de la désérialisation avec JMSSerializerBundle

Mes entités (simplifiées) sont les suivantes. Je laisse de côté le code que je pense est inutile:

Widget 
{ 
    protected $id; 

    /** 
    * @ORM\OneToMany(
    *  targetEntity="Belka\Iso50k1Bundle\Entity\VarSelection", 
    *  mappedBy="widget", 
    *  cascade={"persist", "remove", "detach", "merge"}) 
    * @Serializer\Groups({"o-all-getCWidget", "i-p2-create", "o-all-getWidget", "i-p3-create", "i-p2-editWidget"}) 
    * @Type("ArrayCollection<Belka\Iso50k1Bundle\Entity\VarSelection>") 
    */ 
    protected $varsSelection; 
} 


/** 
* @ORM\Entity() 
* 
* @ORM\InheritanceType("SINGLE_TABLE") 
* 
* @ORM\DiscriminatorColumn(
*  name="vartype", 
*  type="string") 
* 
* @ORM\DiscriminatorMap({ 
*  "PHY" = "PhyVarSelection" 
* }) 
* 
* @ORM\HasLifecycleCallbacks() 
*/ 
abstract class VarSelection 
{ 
    /** 
    * @Id 
    * @Column(type="integer") 
    * @GeneratedValue("SEQUENCE") 
    * @Serializer\groups({"o-all-getCWidget", "o-all-getWidget", "i-p2-editWidget"}) 
    */ 
protected $id; 
} 



class PhyVarSelection extends VarSelection 
{ 
    /** 
    * @var PhyVar 
    * 
    * @ORM\ManyToOne(
    *  targetEntity="Belka\Iso50k1Bundle\Entity\PhyVar", 
    *  cascade={"persist", "merge", "detach"}) 
    * 
    * @ORM\JoinColumn(
    *  name="phy_var_sel", 
    *  referencedColumnName="id", 
    *  nullable=false) 
    */ 
    protected $phyVar; 
} 

class PhyVar extends Variable 
{ 
    /** 
    * @ORM\Column(type="string") 
    * @ORM\Id 
    * 
    * @Serializer\Groups({"o-p2-getCMeters", "o-all-getWidget"}) 
    * @Assert\Regex("/(PHY)_\d+_\d+_\w+/") 
    */ 
    protected $id; 

    /** 
    * @ORM\Column(type="text", name="varname") 
    * @Serializer\Groups({"o-p2-getCMeters", "o-all-getWidget", "o-all-getCWidget"}) 
    */ 
    protected $varName; 

    ... 

} 

J'essaie de désérialiser un objet qui représente une entité Widget déjà persisté, avec lequel un réseau de varselection avec leur propre id spécifié - si elle a déjà persisté - et sans leur propre id si elles sont nouvelles et à persister.

désérialisation fonctionne:

$context = new DeserializationContext(); 
$context->setGroups('i-p2-editWidget'); 
$data = $this->serializer->deserialize($content, $FQCN, 'json', $context); 

mais $data a toujours Widget::$varsSelection[]::$phyVar en tant que classe proxy initialisé, avec seulement le id correctement réglé. Ce que je dois faire pour avoir tout cela est:

foreach ($data->getVarsSelection() as $varSel) { 
    $varSel->getVar(); 
} 

pourquoi est-ce? Comment peut-on l'initialiser déjà? Je ne veux pas passer du temps à faire du vélo et à récupérer des données à partir de la base de données.

modifier

J'ai ajouté un domaine des entités afin d'obtenir l'idée de ce que je suis désérialisation Domain of the entities

Répondre

0

Je me suis moi-même les raisons et les modalités de ce comportement:

depuis que je suis l'envoi d'un JSON comme ce qui suit:

{ 
    "id": <widgetID>, 
    "vars_selection": { 
    "id": <varSelectionID>, 
    "vartype": "PHY" 
    } 
} 

Doctrine de JMSSerializer ObjectConstructor essaie simplement trouve que deux entités: Widget et VarSelection en exécutant la ligne suivante:

$object = $objectManager->find($metadata->name, $identifierList); 

en d'autres termes: EntityManager essaie de trouver l'entité identifiée par son ID de Doctrine. Donc, bien, prenez les classes proxy unitialisées. Pour autant que je sache, find ne peut spécifier un mode d'hydratation. Par conséquent, deux sont les façons de gérer cela:

  1. fetch="EAGER" sur PhyVarSelection::$phyVar Spécifiez. Assez coûteux, quand nous n'en avons pas besoin;
  2. Remplacez le ObjectConstructor en appelant le référentiel et créez un DQL dont l'option EAGER sera correctement définie. Quelque chose comme $query->setFetchMode("PhyVarSelection", "phyVar", \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER);