b174008
b174008

Reputation: 285

Symfony2 ModelTransformer reverseTransform is never called

In Symfony 2.8 I've got Movie entity with actors field, which is ArrayCollection of entity Actor (ManyToMany) and I wanted the field to be ajax-loaded Select2. When I don't use Ajax, the form is:

->add('actors', EntityType::class, array(
        'class' => Actor::class,
        'label' => "Actors of the work",
        'multiple' => true,
        'attr' => array(
          'class' => "select2-select",
         ),
       ))

It works, and this is what profiler displays after form submit: https://i.sstatic.net/9xpOw.png

Actors' amount grown up and I wanted to load them with Ajax autocompleter on Select2. I changed form to ChoiceType:

->add('actors', ChoiceType::class, array(
'multiple' => true,
'attr' => array(
    'class' => "select2-ajax",
    'data-entity' => "actor",
    ),
))
//...
$builder->get('actors')
        ->addModelTransformer(new ActorToNumberModelTransformer($this->manager));

I made DataTransformer:

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Persistence\ObjectManager;
use CompanyName\Common\CommonBundle\Entity\Actor;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

class ActorToNumberModelTransformer implements DataTransformerInterface
{
    private $manager;

    public function __construct(ObjectManager $objectManager)
    {
        $this->manager = $objectManager;
    }

    public function transform($actors)
    {
        if(null === $actors)
            return array();

        $actorIds = array();
        $actorsArray = $actors->toArray();

        foreach($actorsArray as $actor)
            $actorIds[] = $actor->getId();

        return $actorIds;
    }

    public function reverseTransform($actorIds)
    {
        if($actorIds === null)
            return new ArrayCollection();

        $actors = new ArrayCollection();

        $actorIdArray = $actorIds->toArray();

        foreach($actorIdArray as $actorId)
        {
            $actor = $this->manager->getRepository('CommonBundle:Actor')->find($actorId);
            if(null === $actor)
                throw new TransformationFailedException(sprintf('An actor with id "%s" does not exist!', $actorId));

            $actors->add($actor);
        }

        return $actors;
    }
}

And registered form:

common.form.type.movie:
    class: CompanyName\Common\CommonBundle\Form\Type\MovieType
    arguments: ["@doctrine.orm.entity_manager"]
    tags:
        - { name: form.type }

But seems like the reverseTransform() is never called. I even put die() at the beginning of it - nothing happened. This is, what profiler displays after form submit: https://i.sstatic.net/SKUKr.png

I tried to add also ViewTransformer (code here: pastebin -> 52LizvhF - I don't want to paste more and I can't post more than 2 links), with the same result, except that reverseTransform() is being called and returns what it should return.

Upvotes: 1

Views: 421

Answers (1)

Narcissus
Narcissus

Reputation: 3194

I know that this is an old question, but I was having a very similar problem. It turned out that I had to explicitly set the compound option to false.

That is to say, for the third parameter to the add() method, you need to add 'compound => false'.

Upvotes: 2

Related Questions