New in Symfony 5.2: Form mapping callbacks
October 7, 2020 • Published by Javier Eguiluz
Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
Contributed by
Yonel Ceruto
in #37968.
Sometimes, the objects handled with Symfony forms don't define the expected
getter/setter methods (e.g. getName()
and setName()
) but other methods
better aligned with the application needs (e.g. getName()
and rename()
).
In those cases, you can use a form data mapper to move the object data into
the form fields and the other way around. In Symfony 5.2 we've improved this to
allow using callback functions to get/set form fields. You only need to
define the new getter
or setter
options (or both) and Symfony will run
that callback to get/set the value from/into the object/array:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// src/Form/Type/ProductType.php
namespace App\Form\Type;
use App\Entity\Person;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, [
'getter' => function (Person $person, FormInterface $form): string {
return $person->getUserData()->getFirstName();
},
'setter' => function (Person &$person, ?string $name, FormInterface $form): void {
$person->rename($name);
},
])
// ...
;
}
// ...
}
This new feature means that you no longer need to create a data mapper to solve this problem. However, you still need to use data mappers in certain situations (when several form fields are mapped to a single method, when the mapping of the model depends on the submitted form data, etc.)
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
But I think the code example isn't a good example...
Why would you use a singular name input field if the Person interface has a split firstName and lastName?
How is the `rename()` method supposed to split the singular `$name` variable into `firstName` and `lastName`?
Please don't say "look for a space character and split it there". ;-).
Don't get me wrong; I think these kind of examples are way better than the abstract foo-bar-baz ones, but I think this example adds confusion.
It's concise and also is similar to property accessors of other programming languages
And form data could also be an array.
FormMappers are quite verbose and write and not very re-usable, thank you very much for this simplification :)