如何在Symfony 4中将数组提交到未映射的表单字段

时间:2019-02-08 15:19:40

标签: php symfony-forms symfony4 symfony-2.7

我正在尝试将具有值的数组提交到symfony 4表单字段,但是验证一直失败。

我正在将应用程序从symfony 2.7更新到symfony4。问题在于,由于symfony格式的更改,我现在使用的表单始终无法通过验证。

symfony表单具有以下字段

$builder->add('contactData', null, ['mapped' => false])

在symfony 2.7中,我将始终在contactData字段中提交具有数组值的POST请求,由于未映射它,因此它将在提交过程中将数据设置为字段对象,并且在处理程序。请求示例:

{
    "name": {
        "aField": "aValue",
        "contactData": {
             "something": "value"
         }
    }
}

但是在symfony 4中,\Symfony\Component\Form\Form类中现在增加了验证检查

} elseif (\is_array($submittedData) && !$this->config->getCompound() && !$this->config->hasOption('multiple')) {

,这会导致在将数据提交到contactData字段时验证失败,因为SubmittedData确实是一个数组。我一直在互联网上浏览并阅读symfony的文档,但似乎找不到找到与symfony 2.7相同的行为的方法。

我将不胜感激任何建议,我已经坚持了一段时间

2 个答案:

答案 0 :(得分:0)

Symfony从v2.7更改为4.0,更改了许多默认值;

我遇到了同样的问题,经过2个小时的调查, 我最终添加了属性compoundallow_extra_field

因此,这应该可以解决您的问题:

$builder->add('contactData', null, [
    'mapped' => false,
    'compound' => true,
    'allow_extra_fields' => true,
])

编辑

这没有按预期工作,最终我没有出现错误,也没有内容作为提交的数据,所以我创建了一个新类型来在预提交事件中动态添加字段,如下所示:

UnstructuredType.php

<?php

namespace ASTechSolutions\Bundle\DynamicFormBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;

/**
 * Class UnstructuredType.
 *
 * This class is created to resolve the change of form's behaviour introduced in https://github.com/symfony/symfony/pull/29307
 * From v3.4.21, v4.1.10 and v 4.2.2, Symfony requires defining fields and don't accept arrays on a TextType for ex.
 * TODO: this is a temporary solution and needs refactoring by declaring explicitly what fields we define, and then accept on requests
 *
 */
class UnstructuredType extends AbstractType
{
    /**
     * {@inheritDoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
            $this->addChildren($event->getForm(), $event->getData());
        });
    }

    /**
     * @param FormInterface $form
     * @param $data
     */
    public function addChildren(FormInterface $form, $data)
    {
        if (is_array($data)) {
            foreach ($data as $name => $value) {
                if (!is_array($value)) {
                    $form->add($name);
                } else {
                    $form->add($name, null, [
                        'compound' => true
                    ]);

                    $this->addChildren($form->get($name), $value);
                }
            }
        } else {
            $form->add($data, null, [
                'compound' => false,
            ]);
        }
    }
}

答案 1 :(得分:0)

在另一个答案中不需要@ sym183461的UnstructuredType。

该信息在其他字段中。

您定义类似@ sym183461的字段:

$builder->add('contactData', null, [
    'mapped' => false,
    'compound' => true,
    'allow_extra_fields' => true,
])

然后您可以执行以下操作:

$contactData = $form->get('contactData')->getExtraFields()

您所有的数据都在其中,并且可以在深层结构中正常工作。