Symfony 2-一个数据库行的多个表单字段
我用的是Symfony 2.1和Doctrine 2 我正在处理两个主要的实体:地点和特征,它们之间有很多关系。 数据库中有许多功能,要按主题对其进行分组,该功能还与具有多功能关系的FeatureCategory实体相关 以下是不同实体的代码: 地点实体 FeatureCategory实体:Symfony 2-一个数据库行的多个表单字段,symfony,doctrine-orm,symfony-forms,symfony-2.1,Symfony,Doctrine Orm,Symfony Forms,Symfony 2.1,我用的是Symfony 2.1和Doctrine 2 我正在处理两个主要的实体:地点和特征,它们之间有很多关系。 数据库中有许多功能,要按主题对其进行分组,该功能还与具有多功能关系的FeatureCategory实体相关 以下是不同实体的代码: 地点实体 FeatureCategory实体: namespace Mv\MainBundle\Entity; ... /** * @ORM\Entity * @ORM\Table(name="feature_category") */ clas
namespace Mv\MainBundle\Entity;
...
/**
* @ORM\Entity
* @ORM\Table(name="feature_category")
*/
class FeatureCategory
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(name="code", type="string", length=255)
* @Assert\NotBlank()
*/
protected $code;
/**
* @ORM\Column(name="label", type="string", length=255)
* @Assert\NotBlank()
*/
protected $label;
/**
* @ORM\OneToMany(targetEntity="\Mv\MainBundle\Entity\Feature", mappedBy="category", cascade={"persist", "remove"}, orphanRemoval=true)
* @Assert\Valid()
*/
private $features;
public function __construct()
{
$this->features = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set code
*
* @param string $code
* @return Feature
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* Get code
*
* @return string
*/
public function getCode()
{
return $this->code;
}
/**
* Set label
*
* @param string $label
* @return Feature
*/
public function setLabel($label)
{
$this->label = $label;
return $this;
}
/**
* Get label
*
* @return string
*/
public function getLabel()
{
return $this->label;
}
/**
* Add features
*
* @param \Mv\MainBundle\Entity\Feature $features
*/
public function addFeatures(\Mv\MainBundle\Entity\Feature $features){
$features->setCategory($this);
$this->features[] = $features;
}
/**
* Get features
*
* @return Doctrine\Common\Collections\Collection
*/
public function getFeatures()
{
return $this->features;
}
/*
* Set features
*/
public function setFeatures(\Doctrine\Common\Collections\Collection $features)
{
foreach ($features as $feature)
{
$feature->setCategory($this);
}
$this->features = $features;
}
/**
* Remove features
*
* @param Mv\MainBundle\Entity\Feature $features
*/
public function removeFeature(\Mv\MainBundle\Entity\Feature $features)
{
$this->features->removeElement($features);
}
/**
* Add features
*
* @param Mv\MainBundle\Entity\Feature $features
* @return FeatureCategory
*/
public function addFeature(\Mv\MainBundle\Entity\Feature $features)
{
$features->setCategory($this);
$this->features[] = $features;
}
}
要素表已填充,用户将无法添加要素,只能在表单集合中选择要素以将其链接到该位置。
要素实体目前仅链接到位置,但稍后将与我的应用程序中的其他实体关联,并将包含所有实体可用的所有要素
在Place表单中,我需要显示可用于某个位置的功能的复选框,但我需要显示按类别分组的功能。
例如:
访问功能类别-代码VIS:
自由特征
付费功能
语言口语功能类别-代码LAN:
英语特色
法国特色
西班牙特色
我的想法
在我的PlaceType表单中使用虚拟表单,如下所示:
$builder
->add('name')
->add('visit', new FeatureType('VIS'), array(
'data_class' => 'Mv\PlaceBundle\Entity\Place'
))
->add('language', new FeatureType('LAN'), array(
'data_class' => 'Mv\PlaceBundle\Entity\Place'
));
class FeatureType extends AbstractType
{
protected $codeCat;
public function __construct($codeCat)
{
$this->codeCat = $codeCat;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('features', 'entity', array(
'class' => 'MvMainBundle:Feature',
'query_builder' => function(EntityRepository $er)
{
return $er->createQueryBuilder('f')
->leftJoin('f.category', 'c')
->andWhere('c.code = :codeCat')
->setParameter('codeCat', $this->codeCat)
->orderBy('f.position', 'ASC');
},
'expanded' => true,
'multiple' => true
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'virtual' => true
));
}
public function getName()
{
return 'features';
}
}
并创建一个FeatureType虚拟表单,如下所示:
$builder
->add('name')
->add('visit', new FeatureType('VIS'), array(
'data_class' => 'Mv\PlaceBundle\Entity\Place'
))
->add('language', new FeatureType('LAN'), array(
'data_class' => 'Mv\PlaceBundle\Entity\Place'
));
class FeatureType extends AbstractType
{
protected $codeCat;
public function __construct($codeCat)
{
$this->codeCat = $codeCat;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('features', 'entity', array(
'class' => 'MvMainBundle:Feature',
'query_builder' => function(EntityRepository $er)
{
return $er->createQueryBuilder('f')
->leftJoin('f.category', 'c')
->andWhere('c.code = :codeCat')
->setParameter('codeCat', $this->codeCat)
->orderBy('f.position', 'ASC');
},
'expanded' => true,
'multiple' => true
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'virtual' => true
));
}
public function getName()
{
return 'features';
}
}
有了这个解决方案,我得到了我想要的,但是绑定过程并没有保留所有的特性。它没有对它们进行分组,只保留最后一种分组语言,并删除所有以前的功能数据。要查看它的实际运行情况,如果我选中5个复选框,它将进入Place->addFeature函数5次,但features arrayCollection的长度依次为:1、2、1、2、3
你知道怎么用另一种方法吗?如果我需要改变模型,我仍然能够做到。
处理这个问题的最佳方法是什么,在我未来的其他实体上可重用,也与功能相关
谢谢你们。我认为你们最初的需求只是模板制作 因此,您不应该调整表单和实体持久性逻辑以获得所需的自动生成表单 你应该回到基本形式
$builder
->add('name')
->add('features', 'entity', array(
'class' => 'MvMainBundle:Feature',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('f')
//order by category.xxx, f.position
},
'expanded' => true,
'multiple' => true
));
并调整你的form.html.twig我认为你最初的需求只是模板化 因此,您不应该调整表单和实体持久性逻辑以获得所需的自动生成表单 你应该回到基本形式
$builder
->add('name')
->add('features', 'entity', array(
'class' => 'MvMainBundle:Feature',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('f')
//order by category.xxx, f.position
},
'expanded' => true,
'multiple' => true
));
并调整form.html.twig