Yonel Ceruto
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.)

Published in #Living on the edge