2012-10-04 1 views
9

Ho 2 entità - Utente e Gruppo. Hanno una relazione molti-a-molti e Group è utilizzato per memorizzare i ruoli di un utente.Symfony 2 Embedded Form Collection Many to Many

Sto cercando di fare un modulo di modifica per l'utente con l'aggiunta di una collezione, voglio essere in grado di aggiungere un nuovo ruolo selezionandola da un elenco a discesa (limitato a ciò che è già nel DB)

UserType. php:

class UserType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('username') 
      ->add('email') 
      ->add('forename') 
      ->add('surname') 
      ->add('isActive') 
      ->add('joinDate', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy')) 
      ->add('lastActive', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy')) 
      ->add('groups', 'collection', array(
        'type' => new GroupType(), 
        'allow_add' => true, 
        )) 
     ; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Sfox\CoreBundle\Entity\User' 
     )); 
    } 
} 

e GroupType.php:

class GroupType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('name') 
      ->add('role'); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
       "data_class" => 'Sfox\CoreBundle\Entity\Group' 
       )); 
    } 
} 

Questo visualizza i ruoli nella forma in caselle di testo di base, ma se aggiungo una voce al modulo, sarà cascata persisterà un nuovo ent ry nei gruppi e se dovessi modificare una voce, cambierebbe i dati di gruppo sottostanti.

provai a fare un GroupSelectType.php:

class GroupSelectType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('role', 'entity', array('class'=>'SfoxCoreBundle:Group', 'property'=>'name')); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
       "data_class" => 'Sfox\CoreBundle\Entity\Group' 
       )); 
    } 
} 

Aggiunta del campo come un tipo "entità", visualizza la casella di selezione corretta (ma con i valori di default) smusso sembro associarlo alla Modulo UserType!

Tutto quello che voglio che il modulo faccia è modificare l'ArrayCollection "gruppi" sottostante nell'entità Utente.

Qualcuno sa come posso ottenere questo?

risposta

14

Beh ho elaborato una soluzione per chiunque altro alle prese con problemi simili ...

ho dovuto creare un tipo di modulo personalizzato e dichiararlo come servizio in modo da poter passare il gestore di entità. Poi ho bisogno di fare un dataTransformer di cambiare oggetti mio gruppo in un intero per il modulo

personalizzato GroupSelectType:

class GroupSelectType extends AbstractType 

{ 
    /** 
    * @var ObjectManager 
    */ 
    private $om; 

    private $choices; 

    /** 
    * @param ObjectManager $om 
    */ 
    public function __construct(ObjectManager $om) 
    { 
     $this->om = $om; 

     // Build our choices array from the database 
     $groups = $om->getRepository('SfoxCoreBundle:Group')->findAll(); 
     foreach ($groups as $group) 
     { 
      // choices[key] = label 
      $this->choices[$group->getId()] = $group->getName() . " [". $group->getRole() ."]"; 
     } 
    } 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $transformer = new GroupToNumberTransformer($this->om); 
     $builder->addModelTransformer($transformer); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
       "choices" => $this->choices, 
       )); 
    } 

    public function getParent() 
    { 
     return 'choice'; 
    } 

    public function getName() 
    { 
     return 'group_select'; 
    } 
} 

Nel costruttore sto ottenendo tutti i gruppi disponibili e la loro messa in un "scelte" array che viene passato alla casella di selezione come opzione.

Noterai anche che sto utilizzando un trasformatore di dati personalizzato, questo è per modificare il groupId (utilizzato nel rendering del modulo) in un'entità di gruppo. Ho fatto il GroupSelectType un servizio come bene e passato nella [@ doctrine.orm.entity_manager]

services.yml (bundle config):

services: 
    sfox_core.type.group_select: 
     class: Sfox\CoreBundle\Form\Type\GroupSelectType 
     arguments: [@doctrine.orm.entity_manager] 
     tags: 
      - { name: form.type, alias: group_select } 

GroupToNumberTranformer.php

class GroupToNumberTransformer implements DataTransformerInterface 
{ 
    /** 
    * @var ObjectManager 
    */ 
    private $om; 

    /** 
    * @param ObjectManager $om 
    */ 
    public function __construct(ObjectManager $om) 
    { 
     $this->om = $om; 
    } 

    /** 
    * Transforms an object (group) to a string (number). 
    * 
    * @param Group|null $group 
    * @return string 
    */ 
    public function transform($group) 
    { 
     if (null === $group) { 
      return ""; 
     } 

     return $group->getId(); 
    } 

    /** 
    * Transforms a string (number) to an object (group). 
    * 
    * @param string $number 
    * @return Group|null 
    * @throws TransformationFailedException if object (group) is not found. 
    */ 
    public function reverseTransform($number) 
    { 
     if (!$number) { 
      return null; 
     } 

     $group = $this->om 
     ->getRepository('SfoxCoreBundle:Group') 
     ->findOneBy(array('id' => $number)) 
     ; 

     if (null === $group) { 
      throw new TransformationFailedException(sprintf(
        'Group with ID "%s" does not exist!', 
        $number 
      )); 
     } 

     return $group; 
    } 
} 

E my UserType.php modificato - Avviso Sto utilizzando il mio tipo di modulo personalizzato "group_select" ora poiché è in esecuzione come servizio:

class UserType extends AbstractType 
{ 
    private $entityManager; 

    public function __construct($entityManager) 
    { 
     $this->entityManager = $entityManager; 
    } 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $transformer = new GroupToNumberTransformer($this->entityManager); 

     $builder 
      ->add('username') 
      ->add('email') 
      ->add('forename') 
      ->add('surname') 
      ->add('isActive') 
      ->add('joinDate', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy')) 
      ->add('lastActive', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy')); 
     $builder 
      ->add(
       $builder->create('groups', 'collection', array(
        'type' => 'group_select', 
        'allow_add' => true, 
        'options' => array(
          'multiple' => false, 
          'expanded' => false, 
          ) 
        )) 
     ); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Sfox\CoreBundle\Entity\User' 
     )); 
    } 

    public function getName() 
    { 
     return 'sfox_corebundle_usertype'; 
    } 
} 
+0

Questa risposta mi ha aiutato tantissimo! Grazie! – jcbwlkr

+0

Perfetto grazie! –

+0

Molto utile. Grazie – Rinat