Forms Symfony2从集合创建表单

Forms Symfony2从集合创建表单,forms,symfony,collections,types,Forms,Symfony,Collections,Types,我需要创建一个表单来编辑实体列表。这与经典用例(以及我发现的所有示例)不同,在经典用例中,我们有一个作为嵌套实体的实体 在我的情况下,我想使用: $form = $this->get('form.factory')->create( new MyType(), mycollectionofobjects ); 因此表单需要处理一个对象集合(在我的例子中是一个推进集合) 在典型情况下,我们可以使用: $formBuilder->add(

我需要创建一个表单来编辑实体列表。这与经典用例(以及我发现的所有示例)不同,在经典用例中,我们有一个作为嵌套实体的实体

在我的情况下,我想使用:

$form = $this->get('form.factory')->create(
        new MyType(),
        mycollectionofobjects
    );
因此表单需要处理一个对象集合(在我的例子中是一个推进集合)

在典型情况下,我们可以使用:

$formBuilder->add(
            'getTheCollection',
            "collection", etc...

因此,从主对象开始,子窗体是使用getTheCollection的数据构建的,但是,如果没有主实体,它就无法工作。

我在这种情况下使用的解决方案如下

  • 当然,创建一个不会持久化到DB的实体,并且只表示一个容器。差不多

    use Doctrine\Common\Collections\ArrayCollection;
    class YourTypeCollector
    {
        protected $your_type_colletion;
    
        public function __construct() 
        {
            $this->your_type_colletion = new ArrayCollection();
        }
    
        public function setYourTypeCollection(ArrayCollection $yourTypeCollection)
        {
            $this->your_type_collection = $yourTypeCollection
        }
    
        public function getYourTypeCollection()
        {
            return $this->your_type_collection;
        }
    }
    
  • 创建
    YourTypeCollectorForm

    class YourTypeCollectorFormType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder->add('your_type_collection', 'collection', array(
                'type' => new YourTypeType()
            );
        }
    
       public function getName()
       {
           return 'your_type_collector_form';
       }
    
       public function setDefaultOptions(OptionsResolverInterface $resolver)
       {
           $resolver->setDefaults(array(
               'data_class' => 'Path\To\Your\Type\Collector',
                'cascade_validation' => true, //!Important
           ));
        }
    }
    
  • 将其实例化到控制器中,并像“普通”其他具有集合的表单一样使用它

    $your_type_colletor = new YourTypeCollector();
    $your_type_collector->setYourTypeCollection(//an array collection here);
    $form = $this->createForm(new YourTypeCollectorType());
    

我不确定这是否是解决这个问题的最佳方法,但我确信这是可行的,因为我目前将其用于我的旧项目中

另一种可能性可能是这样的(据信是适应性的):

如果存在一个名为Collection的实体,该实体包含一组对象,请创建一个表单视图,以允许编辑所有(或选定)对象

1) 为单个对象创建表单类型:

class CollectionType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('object')
            ;
    }

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

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'YourBundle\Entity\Collection',
        ));
    }
2) 为一组对象创建表单类型

class ObjectsType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('objects', 'collection', ['type' => new CollectionType(),
                    ])
                ))
            ;
    }
3) 在控制器中实例化窗体

public function editObjectsAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $objects = $em->getRepository("YourBundle:Collection")->findAll();
    $form = $this->createForm(new ObjectsType(), array('objects' => $objects));
    ...
}
[希望我已经正确推广了此解决方案的使用!]


对于一个“真实世界”的应用程序,请参见。

谢谢,我是用一个只有方法“getChild”的伪根对象这样做的,然后当我创建子窗体时,我给了参数“child”,仅此而已。我不确定这是不是最好的方法,我很好奇是否有更好(更“漂亮”)的解决方案?你可以使用数组而不是创建一个特殊的集合对象。@Cerad:我很确定你在这里展示的方法,这是显而易见的。但是,正如我在这里所说的,这是我在老项目中使用的一个解决方案,对于这个答案,我只是复制/粘贴/改编到这里:)是的。我想不久前我也做了同样的事情,直到我意识到数组可以很好地工作。@Cerad:你知道这个过程,不是吗?问题->工作代码->良好代码->完美代码:)