我正在研究Symfony2中的Web应用程序.我找到了一些需要Symfony更高级的建议/解释的地方.
我的数据库的一部分设置如下:
我有属于卡属性集的卡,由卡值组成.
我有卡属性集有很多属性,卡属性可以属于许多卡属性集(显然是多对多的关系).
然后,根据card属性,该属性具有属性值,例如,text具有varchar类型的value_text,boolean具有boolean类型的value_boolean.
您可以想象在制作表单以创建新卡时,表单需要根据其所属的卡属性集生成输入字段,并且取决于属于该属性集的属性吗?
所以这是我的问题;有没有办法根据用户选择的实体动态生成表单中的输入字段.我读过有关活动但我不确定它们是否满足我的需求.
这是我的实体的代码(我删除了Getters和Setters以获得更简单的视图):
卡:
/** * 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(); } }
卡属性:
/** * 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",length=255) */ private $name; /** * @var string * * @ORM\Column(name="type",length=255) */ private $type; }
卡属性集
/** * 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",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(); } }
卡属性值
/** * 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",length=255,nullable=true) */ private $valueText; /** * @var string * * @ORM\Column(name="value_varchar",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) */ 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; }
为CardAttributeValue实体创建表单类型CardAttributeValueType,在此表单内添加字段,具体取决于传递的属性类型:
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 } } }
然后,在CardType表单类型中为card_values添加集合字段类型,并将CardAttributeValueType作为集合项类型传递.
在Card实体中编辑getCardValues()方法,因此它将返回CardAttributeSet中的每个属性,而不仅仅是存在值实体的属性.
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; }