2015-11-16 1 views
5

J'ai une entité qui se rapporte à elle-même. L'entité a des champs: parent et enfants.doctrine symfony2 - Ajouter des enfants à une entité auto-apparentée

class A 
{ 
    // ... 

    /** 
    * @var A 
    * @ORM\ManyToOne(targetEntity="A", inversedBy="children") 
    * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true, onDelete="CASCADE") 
    */ 
    protected $parent; 

    /** 
    * @var A[] 
    * @ORM\OneToMany(targetEntity="A", mappedBy="parent", cascade={"all"}, orphanRemoval=true) 
    */ 
    protected $children; 
} 

Je souhaite ajouter des enfants à cette entité en configurant des enfants sous forme. Ce type d'entité ressemble à ceci:

class AType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      // ... 
      ->add('children', 'collection', [ 
       'type' => new AType(), 
       'allow_add' => true, 
       'allow_delete' => true, 
       'by_reference' => false, 
       'prototype' => true, 
      ]) 
     ; 
    } 
} 

Lorsque j'envoie des données comme ceci:

'a' => [ 
    [ 
     'name' => 'main a', 
     'children' => [ 
      [ 
       'name' => 'child a 1', 
      ], 
      [ 
       'name' => 'child a 2', 
      ], 
     ], 
    ], 
], 

(en test, je n'ai pas vue, car cette application est basée sur la communication complète REST Api) Je eu cette erreur:

PHP Fatal error: Maximum function nesting level of '100' reached, aborting!

Alors, est-il même possible d'ajouter des enfants à des entités liées autonomes?

Cela fonctionnerait si j'avais 2 entités: l'entité A avec les enfants du champ liés à l'entité B. Mais, peut-il fonctionner avec cette relation?

Devrais-je changer de type dans la classe AType de new AType() à quelque chose de différent.

EDIT: En fait, je veux juste obtenir des données et les valider. Je n'ai pas besoin de formulaire HTML pour l'afficher. Je peux le faire comme ceci:

// controller 
$jms = $this->get('jms_serializer'); 
$entity = $jms->deserialize($request->getContent(), 'AcmeBundle\Entity\A', 'json'); 

$this->em->persist($entity); 
$this->em->flush(); 

sans utiliser de formulaire dans le contrôleur. Mais dans ce cas, mes données ne seront pas validées.

+0

Essayez-vous de sérialiser votre entité à un moment donné? L'auto-référence peut en être la cause et vous devez implémenter vos propres règles de sérialisation. – stevenll

+0

Non. J'essaie juste d'ajouter ceci et c'est tout. Mon action dans le contrôleur semble totalement normale et renvoie une réponse vide. –

+0

Essayez d'augmenter la valeur xdebug (http: // stackoverflow.com/questions/4293775/augmentant-imbriquant-fonctions-appelle-limite/4293870 # 4293870): 'xdebug.max_nesting_level = 200'. Cela devrait vous donner la vraie erreur. –

Répondre

0

Je vous suggère d'avoir un coup d'oeil ici: https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/tree.md#tree-entity-example

L'id structure DB repose sur d'autres champs stockés dans DB et en dehors de parentID.

modèle de Il est basé sur ce point: https://en.wikipedia.org/wiki/Nested_set_model

+0

Je peux le faire, ce n'est pas un problème. Mais dans cet exemple, ils sont basés sur la définition du parent. J'ai besoin de mettre les enfants et les enfants des enfants. Et aussi besoin de l'utiliser avec le type de formulaire. –

3

PHP Fatal error: Maximum function nesting level of '100' reached, aborting!

Parce que vous avez récursivité. Lorsque vous appelez createForm, il essaie de résoudre type. Vous pouvez trouver cette partie du code dans la fonction FormFactoryresolveType. Je pense que vous pouvez créer un deuxième type de formulaire qui inclut title et parent.

class AType extends AbstractType{ 
    //... 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
    $builder 
     ->add('title') 
     ->add('parent') 
     ->add('children', 'collection', array(
      'type' => new BType(), 
      'allow_add' => true, 
      'allow_delete' => true, 
      'by_reference' => false, 
      'prototype' => true 
     )); 
    } 
} 

class BType extends AbstractType { 
    //.. 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
     ->add('title') 
     ->add('parent'); 
    } 
} 

Je pense que générateur de formulaire peut chercher et carte Content-Type:application/x-www-form-urlencoded. J'ai implémenté avec le format html. J'ai également essayé d'envoyer application/json mais le résultat est infructueux. C'est pourquoi vous pouvez utiliser les validateurs de schéma json ici.

+0

Je pensais à ça. Mais dans ce cas, je ne peux pas mettre en place des données à plusieurs niveaux. Je peux définir seulement 2 niveaux. –