phpsymfonysymfony-formsdatamapper

Nested data mappers in Symfony form types


I recently wanted to do two sets of mappings within a Symfony form type. I don't have the code handy right now, but let's say I wanted to do something like this at the end of my buildForm() method:

$builder->addDataMapper(new MapperThatMapsOneReusableThing($this->glueServiceOne));
$builder->addDataMapper(new MapperThatMapsADifferentReusableThing($this->glueServiceTwo));

The problem is that there is no addDataMapper() method. There is setDataMapper() method and an addViewTransformer() method, but the addDataMapper() method does not exist -- probably for a good reason related to a well-thought-out design choice by the Symfony folks, I would imagine.

A friend suggested using nested dataMapper classes for this. However, when I google "symfony nested data mappers" and some variants, nothing comes up, which makes me wonder whether this is good or even somewhat workable advice.

Can someone give an example of some code or pseudo-code that uses this technique, along with a quick explanation of what the code is doing?


Solution

  • there is no built-in nested dataMapper.

    A dataMapper is generally specialised in one FormType.

    But, you can create your own nested DataMapper. Something like that:

    class MyDataMapper implements DataMapperInterface
    {
    private array $dataMappers = [];
    
    public function mapDataToForms($viewData, \Traversable $forms)
    {
        foreach ($this->dataMappers as $dataMapper) {
            $dataMapper->mapDataToForms($viewData, $forms);
        }
    }
    
    public function mapFormsToData(\Traversable $forms, &$viewData)
    {
        foreach ($this->dataMappers as $dataMapper) {
            $dataMapper->mapFormsToData($forms, $viewData);
        }
    }
    
    public function addDataMapper(DataMapperInterface $dataMapper)
    {
        $this->dataMappers[] = $dataMapper;
    }
    }
    

    And you can implement your use case.