Entity mapping in a Symfony2 choice field with optgroup

JeanValjean picture JeanValjean · Nov 12, 2012 · Viewed 13.2k times · Source

Suppose to have an entity in Symfony2 that has a field bestfriend, which is a User entity selected from a list of User entities that satisfy a complex requirement. You can render this field in a form by specifying that it is an entity field type, i.e.:

$builder->add('bestfriend', 'entity', array(
   'class' => 'AcmeHelloBundle:User',
   'property' => 'username',
));

This form field is rendered as a <select>, where each one of the displayed values is in the form:

<option value="user_id">user_username</option>

So, one would render the field by using the <optgroup> tags to highlight such special feature of the friends.

Following this principle, I created a field type, namely FriendType, that creates the array of choices as in this answer, which is rendered as follows:

$builder->add('bestfriend', new FriendType(...));

The FriendType class creates a <select> organized with the same <option>s but organized under <optgroup>s.

Here I come to the problem! When submitting the form, the framework recognize that the user field is not an instance of User, but it is an integer. How can I let Symfony2 understand that the passed int is the id of an entity of type User?

Answer

JeanValjean picture JeanValjean · Nov 12, 2012

Here follows my solution. Notice that it is not mentioned in the Symfony2 official docs, but it works! I exploited the fact that the entity field type is child of choice.

Hence, you can just pass the array of choices as a param.

$builder->add('bestfriend', 'entity', array(
   'class' => 'AcmeHelloBundle:User',
   'choices' => $this->getArrayOfEntities()
));

where the function getArrayOfEntities() is a function that fills the choice list with the friends of my friends, organized by my friends:

private function getArrayOfEntities(){
    $repo = $this->em->getRepository('AcmeHelloBundle:User');
    $friends = $repo->findAllFriendByComplexCriteria(...);
    $list = array();
    foreach($friends as $friend){
        $name = $friend->getUsername();
        if(count($friend->getFriends())>0){
            $list[$name] = array();
            foreach($friend->getFriends() as $ff){
                $list[$name][$ff->getUsername()] = $ff;
            }
        }
    }
    return $list;
} 

I know the example could be meaningless, but it works...

PS: You need to pass the entity manager to let it working...