Symfony2:如何将使用工厂生成器创建的表单添加到另一个表单的集合类型字段中?

Symfony2: How to add a form created using factory builder into another form's collection type field?

我在运行时从 yml 创建表单。我遍历 yml 文件中的元素并向表单添加适当的字段。根表单是这样创建的

$form = $factory->createBuilder("form", $this->userData);

yml 也可以选择定义集合字段。 集合字段需要提供 type 选项,该选项的类型必须为 stringSymfony\Component\Form\ResolvedFormTypeInterfaceSymfony\Component\Form\FormTypeInterface

但是因为我也在运行时构建嵌入式表单,所以我没有类型,也没有 FormTypeInterface

这是我需要做的示例代码

$options = isset($config["options"]) ? $config["options"]: [];
if ($config['type'] == 'collection') {
    $options['type'] = $this->buildForm($options['template'], $factory);
    unset($options['template']);
    $form->add($config["name"], $config["type"], $options);
}

这里$options['template']是嵌入表单的类型是如何在yml文件中定义的。因此该表单也是在运行时构建的。如何将其嵌入到根表单中?

编辑: 事实上,如果我只有一个字段,比如在集合字段中说 email,那么它就可以正常工作。但是 yml 规范将允许用户在集合字段中定义多个字段。在 symfony 中,这将通过定义嵌入式表单类型并将集合字段类型的 type 选项设置为该表单类型来完成。但是在运行时创建表单时我该怎么做呢?

我通过定义一个在运行时构建表单的表单类型 class 解决了这个问题。将配置(表单设计)传递到构造函数中,buildForm 根据设计添加相应的字段。

class RuntimeFormType extends AbstractType
{
    /**
     * @var string
     */
    private $name;

    /**
     * @var array
     */
    private $config;

    /**
     * RuntimeFormType constructor.
     * @param string $name
     * @param array $config
     */
    public function __construct($name, array $config)
    {
        $this->name = $name;
        $this->config = $config;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        foreach($this->config as $config){
            $options = isset($config["options"]) ? $config["options"]: [];

            if($config['type'] == 'image'){
                $options['data_class']  = null;
                $options['multiple']  = false;

                $options['attr'] = [
                    "accept" => "images/*"
                ];

                $builder->add($config["name"], "file", $options);
            }else{
                $builder->add($config["name"], $config["type"], $options);
            }
        }
    }


    public function getName()
    {
        return $this->name;
    }
}

并且在生成器中,当类型为 collection 时,类型初始化此表单类型并添加到根表单。

if ($config['type'] == 'collection') {
    $template = $options['template'];

    unset($options['template']);
    $options['type'] = new RuntimeFormType($config["name"], $template);

    $form->add($themeConfig["name"], $themeConfig["type"], $options);
}