Dbl0McJim
Dbl0McJim

Reputation: 196

Symfony2 (2.7) Form Entity Data Transformer

I'm trying to customize a selection list's text while using the entity's ID. This is because I want the list options to be specific to the authenticated user. The database text values are Full Name, By City and State, and Anonymous, but I want it to actually display the user's full name (John Smith), User in Denver, CO, and Anonymous. I'm attempting to use a view data transformer to achieve this, but with no luck. I'd rather not use Javascript to achieve this if possible.

Here's my main form type:

<?php

namespace Members\MessagesBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\SecurityContext;


class MessageType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('viewability', 'viewability_entity', array(
                'class' => 'MessagesBundle:Viewability',
                'property' => 'name',
                'required' => true,
            ))
            ->add('body', new MessageBodyType())
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Members\MessagesBundle\Entity\Message',
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'members_messages_message';
    }
}

Here's my custom form type for Viewability (the entity which I would like to transform):

<?php

namespace Members\MessagesBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\SecurityContext;
use Members\MessagesBundle\Form\DataTransformer\MessageNameTransformer;


class ViewabilityType extends AbstractType
{
    private $context;

    /**
     * @param SecurityContext $context
     */
    public function __construct(SecurityContext $context)
    {
        $this->context = $context;
    }

    /**
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new MessageNameTransformer($this->context);
        $builder->addViewTransformer($transformer);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'invalid_message' => 'The selected issue does not exist',
        ));
    }

    /**
     * @return string
     */
    public function getParent()
    {
        return 'entity';
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'viewability_entity';
    }
}

Here's my service which defines the Viewability Type:

members.messages.form.type.viewability_entity:
        class: Members\MessagesBundle\Form\ViewabilityType
        tags:
            - { name: form.type, alias: viewability_entity }
        arguments: [@security.context]

Here's my Viewability Entity:

<?php

namespace Members\MessagesBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 */
class Viewability
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    public function __construct()
    {
    }

    /**
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param mixed $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param mixed $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }
}

Finally, here's my data transformer:

<?php

namespace Members\MessagesBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Members\MessagesBundle\Entity\Viewability;
use Symfony\Component\Security\Core\SecurityContext;

class MessageNameTransformer implements DataTransformerInterface
{
    private $user;

    /**
     * @param SecurityContext $context
     */
    public function __construct(SecurityContext $context)
    {
        $this->user = $context->getToken()->getUser();
    }

    /**
     * @param Viewability|null $viewability
     * @return string
     */
    public function transform($viewability)
    {
        if (null === $viewability) {
            return '';
        }

        if($viewability === 'Full Name')
            return sprintf('%s %s', $this->user->getInfo()->getFirstName(), $this->user->getInfo()->getLastName());
        if($viewability === 2)
            return sprintf('Lawyer in %s,  %s', $this->user->getInfo()->getAddress()->getCity(), $this->user->getInfo()->getAddress()->getState());
        if($viewability === 3)
            return 'Anonymous';
    }

    /**
     * @param Viewability $viewability
     * @return Viewability
     */
    public function reverseTransform($viewability)
    {
        return $viewability;
    }
}

The data passed into transform() always seems to be null or "" (empty string).

Thanks for any help.

Upvotes: 0

Views: 830

Answers (1)

Dbl0McJim
Dbl0McJim

Reputation: 196

So I ended up taking a different approach to solving this. Originally I was trying to transform data coming from an entity. Fortunately this entity didn't really need to be a database entity after all and a simple choice type sufficed. This doesn't solve the specific issue of transforming an entity list, but it allows me to customize the drop down list values.

The viewability entity was removed and the relationship in the Message entity was changed to an integer field.

My main type is now as follows:

class MessageType extends AbstractType
{
    private $user;

    public function __construct($user)
    {
        $this->user = $user;
    }

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('body', new MessageBodyType())
            ->add('viewability', 'choice', array(
                'choices'   => array(
                    1 => $user->getFirstName(),
                    2 => $user->getAddress()->getCity(),
                    3 => 'Anonymous',
                ),
                'multiple'  => false,
                'label'     => 'Send Message As',
                'data'      => 0,
            ))
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class'    => 'Members\MessagesBundle\Entity\Message',
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'members_messages_message';
    }
}

Upvotes: 0

Related Questions