2013-07-29 13 views
8

Ho 3 soggetti:Symfony2 Form Builder selezione che Join Tavolo con metadati

[Member] ----OneToMany----> [MemberCategory] ---ManyToOne---> [Category] 

Questo funziona risultati bene per quanto riguarda fetching dal database, ma non riesco a ottenere il Form Builder per costruire una forma corretta controlli.

Desidero un elenco di tutte le categorie con caselle di controllo controllate per le categorie utilizzate dal membro. Alla fine voglio aggiungere il campo prioritario.

Stati

class Member 
{ 
    protected $id; 

    @ORM\OneToMany(targetEntity="MemberCategory", mappedBy="member") 
    protected $categories; 
} 

Categoria

class Category 
{ 
    protected $id; 

    @ORM\Column(name="category_name", type="string", length=50, nullable=false, unique=true) 
    private $categoryName; 
} 

MemberCategory

class MemberCategory 
{ 
    @ORM\Id 
    @ORM\ManyToOne(targetEntity="Member") 
    @ORM\JoinColumns({ 
    @ORM\JoinColumn(name="member_id", referencedColumnName="id", onDelete="CASCADE") 
    private $member; 

    @ORM\Id 
    @ORM\ManyToOne(targetEntity="Category") 
    @ORM\JoinColumns({ 
    @ORM\JoinColumn(name="category_id", referencedColumnName="id", onDelete="CASCADE") 
    private $category; 

    @ORM\Column(name="priority", type="integer", nullable=true) 
    protected $priority; 
} 

att Obvious empts con il form builder che non funziona.

se uso:

$builder->add('categories', 'entity', array(
    'class'  => 'SMWMemberBundle:Category', 
    'property'  => 'categoryName', 
    'multiple'  => true, 
    'expanded'  => true, 
    'required'  => false 
)); 

ottengo una select con tutte le categorie, ma nessuno di quelli selezionati in MemberCategory per questo utente.

se uso:

$builder->add('categories', 'entity', array(
    'class'  => 'SMWMemberBundle:MemberCategory', 
    'property'  => 'category.categoryName', 
    'multiple'  => true, 
    'expanded'  => true, 
    'required'  => false 
)); 

ricevo tutte le categorie selezionate per tutti gli utenti.

Qualcuno sa come farlo funzionare, questo è un modello comune ovvio nei dati relazionali e sarebbe facile utilizzando SQL e PHP.

C'è una soluzione semplice in Symfony 2.3 e Doctrine?

risposta

1

Sarà necessario utilizzare il QueryBuilder all'interno del vostro modulo

$builder->add('categories', 'entity', array(
     'class' => 'SMWMemberBundle:MemberCategory', 
     'property'  => 'category.categoryName', 
     'query_builder' => function(EntityRepository $er) use (?) { 
      return $er->createQueryBuilder(?) 

      // your query with a left join probably 

     } 
     'multiple'  => true, 
     'expanded'  => true, 
     'required' => false 
    )); 

vedere la documentazione per un uso corretto. vedono symfony2 form querybuilder with parameters per un exmple

+0

Si prega di completare la vostra rispondi, poiché la parte principale è commentata nella tua risposta – Trix

3

Ecco come ho risolto questo problema in passato (applicato al tuo esempio), ma questo è quello che ho capito quindi potrebbe non essere al 100% giusto per il vostro caso.

Innanzitutto creare un tipo MemberCategory modulo che gli corrisponde:

<?php  
namespace Company\YourBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class MemberCategoryType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('priority') 
      ->add('category', 'entity', 
        array('property' => 'name', 
         'class' => 'CompanyYourBundle:Category')) 
     ; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Company\YourBundle\Entity\MemberCategory' 
     )); 
    } 

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

Quindi aggiungere questo tipo di modulo all'interno del modulo Member Tipo:

<?php 

namespace Company\YourBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class MemberType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('name') 
      ->add('members', 'collection', array(
       'type' => new MemberCategoryType(), 
       'allow_add' => true, 
       'allow_delete' => true, 
       'by_reference' => false,)); 
     ; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Company\YourBundle\Entity\Member' 
     )); 
    } 

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

Quindi è possibile seguire the documentation per aggiungere tutte le categorie vuoi i tuoi membri e assegnare una priorità ogni volta.

+0

La documentazione fa apparire che aggiungere e rimuovere categorie sarebbe un enorme ammontare di problemi, incluso il codice lato client. È questo il caso o sto fraintendendo i documenti? –

+0

Hai letto bene! È così che l'ho fatto, non sono sicuro che sia il modo migliore per me. Vedrò anche le altre risposte perché sono d'accordo con te sul fatto che questo è un modello comune senza alcuna documentazione chiara sul sito ufficiale. – cheesemacfly

+1

Grazie, i documenti di Doctrine descrivono come affrontarlo dal lato dell'entità in http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html (vedi utilizzare il caso 3). Ma non forniscono nulla sull'utilizzo di questo con un modulo Symfony. –

0

Il post di cheesemacfly non è poi così male, ma è una forma incorporata alla chiamata e può essere complicato da gestire. In realtà, si jus necessario creare un "repository personalizzati" http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes

Si aggiungerà un nuovo metodo per "afferrare" il vostro oggetto ORM con Doctrine2 come find() o findBy();

1) Creare un nuovo repository in una cartella del repository della vostra Bundle

<?php 
    namespace YourVendor\SMWMemberBundle\Repository; 
    use Doctrine\ORM\EntityRepository; 

    class CategoryRepository extends EntityRepository{ 

    public function UsedByMember($member){ 
    return $this 
     ->createQueryBuilder('c') 
     ->leftJoin('c.Member', 'mc') 
     ->where('mc.member = ?1') 
     ->setParameter(1, $member); 
} 

}

2) In allegato il repository Cutom al Entity

namespace YourVendor\SMWMemberBundle\Entity; 
use Doctrine\ORM\Mapping as ORM; 

/** 
* @ORM\Entity(repositoryClass="YourVendor\SMWMemberBundle\Entity\ProductRepository") 
* @ORM\Table(name="Category") 
*/ 
class Category{ 

3) aggiungere un costruttore alla classe Form e pass de Entity Manager e la variabile richiesta alla query:

class CategoryUserForm extends AbstractType 
{ 
    private $em; 
    private $member ; 


    public function __construct(EntityManager $em, $site, $seed) 
    { 
     $this->em = $em; 
     $this->member = $member; 

    } 

public function buildForm(FormBuilder $builder, array $options) 
{ 
    $qb = $this->em->getRepository('SMWMemberBundle:Category')->UsedByUsers($this->member); 
    $builder->add('categories', 'entity', array(
     'class' => 'SMWMemberBundle:MemberCategory', 
     'query_builder'  => $qb, 
     'multiple'  => true, 
     'expanded'  => true, 
     'required' => false 
    )); 
} 

4) Nel vostro controller, si crea la forma del genere:

$editForm = $this->createForm(new CategoryUserForm($em, $member), $category); 

Sentitevi liberi di farmi domande, io sono la speranza questo è quello che state cercando;)

Problemi correlati