Reputation: 1762
We are using Symfony Forms for our API to validate request data. At the moment we are facing a problem with the CollectionType
which is converting the supplied value null
to an empty array []
.
As it is important for me to differentiate between the user suppling null
or an empty array I would like to disable this behavior.
I already tried to set the 'empty_data'
to null
- unfortunately without success.
This is how the configuration of my field looks like:
$builder->add(
'subjects',
Type\CollectionType::class,
[
'entry_type' => Type\IntegerType::class,
'entry_options' => [
'label' => 'subjects',
'required' => true,
'empty_data' => null,
],
'required' => false,
'allow_add' => true,
'empty_data' => null,
]
);
The form get's handled like this:
$data = $apiRequest->getData();
$form = $this->formFactory->create($formType, $data, ['csrf_protection' => false, 'allow_extra_fields' => true]);
$form->submit($data);
$formData = $form->getData();
The current behavior is:
Input $data
=> { 'subjects' => null }
Output $formData
=> { 'subjects' => [] }
My desired behavior would be:
Input $data
=> { 'subjects' => null }
Output $formData
=> { 'subjects' => null }
Upvotes: 1
Views: 1501
Reputation: 1762
After several tries I finally found a solution by creating a From Type Extension in combination with a Data Transformer
By creating this form type extension I'm able to extend the default configuration of the CollectionType
FormType. This way I can set a custom build ModelTransformer
to handle my desired behavior.
This is my Form Type Extension:
class KeepNullFormTypeExtension extends AbstractTypeExtension
{
public static function getExtendedTypes(): iterable
{
return [CollectionType::class];
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->addModelTransformer(new KeepNullDataTransformer());
}
}
This one needs to be registered with the 'form.type_extension'
tag in your service.yml:
PrivateApiBundle\Form\Extensions\KeepNullFormTypeExtension:
class: PrivateApiBundle\Form\Extensions\KeepNullFormTypeExtension
tags: ['form.type_extension']
Please note that you still use the
CollectionType
in your FormType and not theKeepNullFormTypeExtension
as Symfony takes care about the extending...
In the KeepNullFormTypeExtension
you can see that I set a custom model transformer with addModelTransformer
which is called KeepNullDataTransformer
The KeepNullDataTransformer
is responsible for keeping the input null
as the output value - it looks like this:
class KeepNullDataTransformer implements DataTransformerInterface
{
protected $initialInputValue = 'unset';
/**
* {@inheritdoc}
*/
public function transform($data)
{
$this->initialInputValue = $data;
return $data;
}
/**
* {@inheritdoc}
*/
public function reverseTransform($data)
{
return ($this->initialInputValue === null) ? null : $data;
}
}
And that's it - this way a supplied input of the type null
will stay as null
.
More details about this can be found in the linked Symfony documentation:
Upvotes: 1