How to use Symfony’s EntityType to Make a Dynamic Dropdown List

Making a form element in Symfony be populated by a list of entities isn’t too hard, but it’s a got some quirkiness to it.

To do this you need the following.

  1. An entity that has more than one of it stored in your database.
  2. A form class.
  3. An entity repository class.

First create your form class like this.

$builder->add('beer', EntityType::class, array(
  'label' => 'Beer',
  'class'=>'MyBundle:Beer',
  'property'=>'name',
  'query_builder'=>function(EntityRepository $er) {
         return $er->getBeers();
   }))
   ->add('drink', SubmitType::class, array(
         'label' => 'Drink this beer'
   ));

Then create a Beer entity that has an attribute “name.” Update your database and add a few beers to the table. If you don’t know how to do this, check out the Symfony documentation on creating and retrieving entities from a database.

Now create BeerRepository class. It should live alongside your Beer.php entity class in the “entity” directory.

In the BeerRepository, create the method mentioned above – getBeers.

public function getBeers()
{
  $query = $this->getEntityManager()->createQueryBuilder()
        ->select('b')
        ->from('MyBundle:Beer', 'b')
        ;
   return $query;
}

This method builds a query that the form will use to pull all of the beers out of the database and display them in a drop down list.

There’s one thing that tripped me up. It’s that part of the form about “property.”

'property'=>'name'

What that is saying is, in the dropdown, display the beer name. I knew there had to be way to tell the form which field to use, but it took forever for me to figure out it was this property attribute.

You could also define a __toString method in the Beer entity class that looks like this.

public function __toString()
{
  return $this->name;
}

If you do it in the entity, it’s the same for every time this entity is used in a dropdown or radio button context. If you do it in the form, you can change it on a form-by-form basis. I guess the form setting would override the __toString, but I haven’t tested it. I like doing it in the form builder, it seems appropriate to be there as it is really related to the form creation.

To change it from a dropdown to radio button, add ‘expanded’=>TRUE to the form builder. If you want the use to be able to select more than one option, like with checkboxes, add ‘multiple’=>TRUE. And while we’re at it, if you set expanded to FALSE and leave multiple to TRUE, you will get a box listing all of the beers, allowing you to select more than on.

As always, drink at home, or drink safely.

Share Button