1

I'm trying to submit array with values to a symfony 4 form field but the validation keeps failing.

I'm in the process of updating my application from symfony 2.7 to symfony 4. The problem is that a form that I used to use now always fails validation due to changes in symfony forms.

The symfony form has the following field

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

In symfony 2.7 I would always submit a POST request with array values in the contactData field and since it's not mapped it would just set the data to the field object in the submit process and the values were accessed in the Handler. Example request:

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

However in symfony 4 there is now an added validation check in the \Symfony\Component\Form\Form class

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

that causes the validation to fail when submiting data to the contactData field, since the submittedData is indeed an array. I've been looking all over the internet and reading through the documentation of symfony but I can't seem to find a way to induce the same behavior as in symfony 2.7.

I would much appreciate any advice, I've been stuck on this for a while

Dylan
  • 11
  • 1
  • 2

2 Answers2

0

Symfony has changed from v2.7 to 4.0, there is a lot of default values changed;

I faced the same problem and after 2 hours of investigations, I ended up adding the attributes compound and allow_extra_field.

So, this should solve your problem:

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

EDIT:

This didn't work as expected, I ended up with no error and no content as a submitted data, so I created a new type to add fields dynamically on a pre-submit event as following:

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,
            ]);
        }
    }
}

ibousfiha
  • 21
  • 8
0

No need @sym183461's UnstructuredType in the other answer.

The information is in the extra fields.

You define the field like @sym183461 said:

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

And then you can do this:

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

All your data is in there, and it works with deep structures just fine.

Radu C
  • 1,340
  • 13
  • 31