确实有更好的方法。
实体创建
创建两个Entity POPO 并将many-to-one 关系分配给子实体的其中一个字段(您已正确完成此操作)。您可能还想在父级中定义one-to-many 关系
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="Child", mappedBy="parent", cascade={"persist", "remove" }, orphanRemoval=true)
*/
protected $children;
我不确定是否有必要,但您应该在设置器中明确设置关系以确保确定。例如在您拥有的实体中:
public function addChild(ChildInterface $child)
{
if(!$this->hasChild($child))
{
$this->children->add($child);
$child->setParent($this);
}
}
Doctrine 可能不会使用这些方法来绑定帖子数据,但自己拥有它可能会解决几个持续存在的问题。
表单类型创建
为两个实体创建一个表单类型
/**
* This would be the form type for your sub-albums.
*/
class ChildType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
//$builder->add(...);
//...
}
public function getDefaultOptions(array $options) {
return array(
'data_class' => 'Acme\Bundle\DemoBundle\Entity\Child'
);
}
public function getName()
{
return 'ChildType';
}
}
/**
* This would be the form type for your albums.
*/
class ParentType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
// This part here describes the relationship between the two
// form types.
$builder->add('children', 'collection', array(
'type' => new ChildType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true
));
}
public function getName()
{
return 'ChildType';
}
}
使用allow_add 和allow_delete 选项,您有效地告诉Symfony,用户可以从集合中添加或删除实体。 prototype 选项可让您在页面上拥有所谓的子表单的原型。
控制器
为了安全起见,您也应该在此处强制执行关系。我已将其隐藏在单独的实体管理器层中(对于更复杂的实体,我有单独的管理器),但您当然也可以在控制器中执行此操作。
foreach($parent->getChildren() as $child)
{
if($child->getParent() === NULL)
{
$child->setParent($parent);
}
}
查看
准备表单模板。原型应该通过在模板中的某处调用form_rest(form) 来呈现。如果没有,或者您想自定义原型,这里有一个示例说明如何进行。
<script id="ParentType_children_prototype" type="text/html">
<li class="custom_prototype_sample">
<div class="content grid_11 alpha">
{{ form_widget(form.children.get('prototype').field1) }}
{{ form_widget(form.children.get('prototype').field2) }}
{{ form_rest(form.children.get('prototype') ) }}
</div>
</li>
</script>
您必须使用 JavaScript 使表单动态化。如果您使用jQuery,您可以通过调用$('ParentType_children_prototype').html() 访问原型。向父级添加新子级时,务必将原型中所有出现的$$name$$ 替换为正确的索引号。
我希望这会有所帮助。
编辑我刚刚注意到有一个关于CollectionType 的article in the Symfony2 Form Type reference。对于如何为此实现前端,它有一个很好的替代方案。