Symfony 2中的表单,其字段的数量和用途会根据外部数据而变化


Form in Symfony 2 whose fields change in number and purpose according to external data

我正在使用Symfony 2构建一个应用程序,其中一个页面包含一个大型表单,其中有许多固定字段,但也有许多字段,其存在和数量完全取决于从DB获取的相关数据。更具体地说,表单提出了许多问题,这些问题本身来自数据库,具有不同的文本和id。答案需要存储在数据库中,并链接到问题。

我已经阅读了Symfony如何处理表单(基本Symfony表单),包括表单对象和支持它的数据对象之间的关系,从表单对象创建字段,以及根据应用于表单对象的规则验证输入。

因为我不想要一个固定的表单对象,我看了看你是如何动态修改表单(动态Symfony表单),但那里的例子似乎是关于选择是否显示某些预定义字段,或控制字段中的选项,而不是从头开始完全生成新的字段,这是我想要的。

我看了一下关于数据转换器的Symfony页面,它似乎是相关的,但我不太明白它将如何帮助我。它们似乎更多的是将表单对象映射到实体,而不是将复杂的表单提交映射到表单对象。

我确实看到了这个SO的答案,在那里的对象支持的形式对象只是一个数组,这似乎也相关:我认为也许答案是生成一些匿名对象与动态字段,然后使表单,但我不知道我如何设置Symfony验证它,我的形式是不完全不同的每次,所以不需要完全匿名。

使用Symfony 2实现这一目标的最佳方法是什么?理想情况下,不放弃框架的优点,如易于验证等?

我以前没有听说过Symfony表单集合,看起来这可能会做我想要的-在我的情况下,每个问题将映射到一个单独的子表单对象。

你的问题很广泛,但这可能有助于集中注意力。

我有一个DynamicFormType,它可以根据配置项数组向表单添加元素。

class DynamicFormType extends AbstractType
{
protected $name;
protected $items;
public function getName() { return $this->name; }
public function __construct($name, $items)
{
    $this->name  = $name;
    $this->items = $items;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{   
    foreach($this->items as $name => $item)
    {
        switch($item['type'])
        {
            case 'radio':
                $attr = array('class' => 'radio-medium');
                $builder->add($name,'choice',array(
                    'label'       => $item['label'],
                    'required'    => false,
                    'attr'        => $attr,
                    'empty_value' => false,
                    'expanded'    => true,
                    'multiple'    => false,
                    'choices'     => $item['choices'],
                ));
                break;
            case 'select':
                $attr = array();
                $builder->add($name,'choice',array(
                    'label'       => $item['label'],
                    'required'    => false,
                    'attr'        => $attr,
                    'empty_value' => false,
                    'expanded'    => false,
                    'multiple'    => false,
                    'choices'     => $item['choices'],
                ));
                break;
            case 'text':
                $attr = array();
                if (isset($item['size'])) $attr['size'] = $item['size'];
                $builder->add($name,'text',array(
                    'label'    => $item['label'],
                    'required' => false,
                    'attr'     => $attr,
                ));
                break;
            case 'textarea':
                $attr = array();
                if (isset($item['rows'])) $attr['rows'] = $item['rows'];
                if (isset($item['cols'])) $attr['cols'] = $item['cols'];
                $builder->add($name,'textarea',array(
                    'label'    => $item['label'],
                    'required' => false,
                    'attr'     => $attr,
                ));
                break;
            case 'collection':
                $dynamicType = new DynamicFormType($name,$item['items']);
                $builder->add($name,$dynamicType,array(
                    'label'    => false,
                    'required' => false,
                ));
                break;
        }
    }
    return; if ($options);
}
}

我相信您可以看到items数组是如何用于创建表单元素的。在我的应用程序中,我使用这个:

    $basicType = new DynamicFormType('basic',$project->getPlan());
    $builder->add('basic',$basicType, array('label' => false));

$project->getPlan()返回items数组,其中描述了我想要添加的各种元素。

希望您可以从这样的东西开始,并找出需要从数据结构中添加哪些元素。我在这里不需要验证,但是一旦事情开始工作,向元素添加约束信息应该很容易。

好的,最后我想要的不是一个真正的动态表单(但感谢@Cerad的代码),而是一个使用集合,其中某些子表单项的数量是可变的。

所以我基本上是按照Symfony文档关于集合的