After hours of debugging the complete vendor/symfony/form/Form I was only able to find out that the FormEvents::SUBMIT converts my null value to Object.
This is my code.
$form = $this->createForm(PersonType::class, new Person());
$form->submit($request->request->all(), false);
if ($form->isSubmitted() && $form->isValid())
{
$em->persist($entity);
$em->flush();
return $entity;
}
return $form->getErrors(true, true);
Then I send this request.
POST /api/persons/e3d90966-b2e7-4503-959f-da989c73c185
{
"name": {"firstName": "John", "lastName": "Doe"}
}
It sets the name of the person to John Doe.
Now I want to clear it:
POST /api/persons/e3d90966-b2e7-4503-959f-da989c73c185
{
"name": null
}
And et voilà: The name is still John Doe.
I'm using a custom type:
class NameType extends AbstractType
{
private EntityManagerInterface $manager;
public function __construct(EntityManagerInterface $manager)
{
$this->manager = $manager;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->add('firstName', TextType::class)
->add('lastName', TextType::class)
;
$builder->addModelTransformer(new NameTransformer($this->manager));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Name::class,
'compound' => true
]);
}
}
And is used via:
$builder
->add('name', NameType::class)
;
Some more informations:
If you are posting
{
"name": null
}
That is the parent form being empty, so without the child form fields you have not passed any values for fields nor the fields themselves. You don't submit a new value for the fields, so nothing is changed.
I think you need to explicitly set each of the individual field values to null in order for this to work. One of the following examples should do the trick:
POST /api/persons/e3d90966-b2e7-4503-959f-da989c73c185
{
"name": {"firstName": null, "lastName": null}
}
or
POST /api/persons/e3d90966-b2e7-4503-959f-da989c73c185
{
"name": {"firstName": "", "lastName": ""}
}