2015-06-18 17 views
7

Sto lavorando a un'applicazione web in Symfony2. Sono arrivato a un punto in cui ho bisogno di qualche consiglio/spiegazione da qualcuno più avanzato di Symfony.Dipendenze nelle forme Symfony2

Ho una parte della mia banca dati che è impostato come segue:

ho carte che appartengono ad un attributo carta set ed è costituito da valori della carta.

Ho set di attributi di scheda con molti attributi, un attributo di scheda può appartenere a molti set di attributi di scheda (ovviamente una relazione molti a molti).

Quindi, a seconda dell'attributo della scheda, l'attributo ha un valore di attributo, ad esempio un testo ha un valore_text di tipo varchar e un booleano ha un valore booleano di valore booleano.

È possibile immaginare quando si crea un modulo per creare una nuova scheda, il modulo deve generare campi di input in base all'insieme di attributi della scheda a cui appartiene e in base agli attributi che appartengono all'insieme di attributi giusto?

Quindi, ecco la mia domanda; c'è un modo per generare dinamicamente campi di input in una forma che dipende dall'entità scelta dall'utente. Ho letto di eventi ma non sono sicuro che soddisfino i miei bisogni.

Questo è il codice per i miei soggetti (ho tolto per getter e setter per una più semplice visualizzazione):

Carta:

/** 
* card 
* 
* @ORM\Table() 
* @ORM\Entity(repositoryClass="clientsBundle\Entity\cardRepository") 
* @UniqueEntity(
*  fields={"cardLabel"}, 
*  message="A card with this label already exists" 
*) 
*/ 
class card 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="card_label", type="string", length=999) 
    */ 
    private $cardLabel; 

    /** 
    * @ORM\ManyToOne(targetEntity="project", inversedBy="project_cards") 
    * @ORM\JoinColumn(name="project_id", referencedColumnName="id", onDelete = "SET NULL") 
    */ 
    protected $card_project; 

    /** 
    * @ORM\ManyToOne(targetEntity="cardAttributeSet", inversedBy="cas_cards") 
    * @ORM\JoinColumn(name="cas_id", referencedColumnName="id") 
    **/ 
    protected $cardAttrSet; 

    /** 
    * @ORM\OneToMany(targetEntity="cardAttrValue", mappedBy="card", cascade={"persist"}, orphanRemoval=true) 
    **/ 
    protected $card_values; 

    /** 
    * @ORM\ManyToMany(targetEntity="user", mappedBy="cards") 
    */ 
    private $users; 

    public function __construct() { 
     $this->card_values = new ArrayCollection(); 
     $this->users = new ArrayCollection(); 
    } 
} 

attributo della carta:

/** 
* cardAttribute 
* 
* @ORM\Table() 
* @ORM\Entity(repositoryClass="clientsBundle\Entity\cardAttributeRepository") 
* @UniqueEntity(
*  fields={"name"}, 
*  message="An attribute with this name already exists" 
*) 
*/ 
class cardAttribute 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="name", type="string", length=255) 
    */ 
    private $name; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="type", type="string", length=255) 
    */ 
    private $type; 
} 

Set di attributi scheda

/** 
* cardAttributeSet 
* 
* @ORM\Table() 
* @ORM\Entity(repositoryClass="clientsBundle\Entity\cardAttributeSetRepository") 
* @UniqueEntity(
*  fields={"casLabel"}, 
*  message="An attribute set with this label already exists" 
*) 
*/ 
class cardAttributeSet 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    public $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="cas_label", type="string", length=255) 
    */ 
    private $casLabel; 

    /** 
    * @ORM\OneToMany(targetEntity="card", mappedBy="cardAttrSet") 
    */ 
    private $cas_cards; 

    /** 
    * @ORM\ManyToMany(targetEntity="cardAttribute") 
    * @ORM\JoinTable(name="cas_attribute", 
    *   joinColumns={@ORM\JoinColumn(name="cas_id", referencedColumnName="id")}, 
    *   inverseJoinColumns={@ORM\JoinColumn(name="attribute_id", referencedColumnName="id")} 
    *   ) 
    */ 
    private $attributes; 

    public function __construct() 
    { 
     $this->cas_cards = new ArrayCollection(); 
     $this->attributes = new ArrayCollection(); 
    } 
} 

scheda Attributo Valore

/** 
* cardAttrValue 
* 
* @ORM\Table() 
* @ORM\Entity(repositoryClass="clientsBundle\Entity\cardAttrValueRepository") 
* @UniqueEntity(
*  fields={"valueText"} 
*) 
*/ 
class cardAttrValue 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="value_text", type="string", length=255, nullable=true) 
    */ 
    private $valueText; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="value_varchar", type="string", length=255, nullable=true) 
    */ 
    private $valueVarchar; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="value_int", type="integer", nullable=true, nullable=true) 
    */ 
    private $valueInt; 

    /** 
    * @var boolean 
    * 
    * @ORM\Column(name="value_boolean", type="boolean", nullable=true, nullable=true) 
    */ 
    private $valueBoolean; 

    /** 
    * @ORM\ManyToOne(targetEntity="card", inversedBy="card_values") 
    * @ORM\JoinColumn(name="card_id", referencedColumnName="id") 
    **/ 
    private $card; 

    /** 
    * @ORM\ManyToOne(targetEntity="cardAttribute") 
    * @ORM\JoinColumn(name="cardAttributes_id", referencedColumnName="id") 
    **/ 
    private $cardAttribute; 
} 

risposta

3

Creare un modulo tipo CardAttributeValueType per CardAttributeValue entità, all'interno di questo modulo aggiungere campi a seconda del passato tipo di attributo:

class CardAttributeValueType extends AbstractType 

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) { 
     $value = $event->getData(); 
     $form = $event->getForm(); 

     if (!$value) { 
      return; 
     } 

     switch ($value->getCardAttribute()->getType()) { 
      case 'text': 
       $form->add('valueVarchar', 'text'); 
       break; 

      // Same for other attribute types 
     } 
    } 
} 

Quindi, aggiungere collection tipo di campo per card_values all'interno del tipo di modulo CardType e passaggio CardAttributeValueType come tipo di elemento di raccolta.

Nel metodo Card modifica entità getCardValues() in modo da restituire ogni attributo da CardAttributeSet, non solo quelli per cui esistono entità valore.

UPDATE

public function getCardValues() 
{ 
    $collection = new ArrayCollection(); 

    if (!$this->cardAttrSet) { 
     return $collection; 
    } 

    // Add existing values 
    foreach ($this->card_values as $value) { 
     $collection[$value->getCardAttribute()->getId()] = $value; 
    } 

    // Get all attributes from the set and create values for missing attributes 
    foreach ($this->cardAttrSet->getAttributes() as $attr) { 
     if (!isset($collection[$attr->getId()])) { 
      $value = new cardAttrValue(); 
      $value->setCardAttribute($attr); 

      $collection[$attr->getId()] = $value; 
     } 
    } 

    return $collection; 
} 
+0

Ha funzionato, grazie mille! –

+0

Vadim Ashikhman, solo la mia modale funziona, perché la carta ha dei valori. Ho ancora bisogno di assicurarmi che il mio getCardValues ​​() restituisca ogni attributo da CardAttributeSet, non solo quelli per cui esistono entità di valore.Ho fatto delle ricerche ma sono abbastanza confuso adesso, hehe. Potresti aiutarmi ancora una volta, per favore? –

+1

Ho aggiornato la mia risposta. Non ho testato questo metodo, penso che ti verrà un'idea. –

Problemi correlati