Symfony2: How to filter the options of an entity-choice form field by a certain attribute?

squirrel picture squirrel · May 18, 2014 · Viewed 13.6k times · Source

1.) The Situation (simplified)

I have two entities: a Container-entity, which has exactly 1 Content-entity. The content_id is stored in the Container-entity.

2.) Soft-Delete Content-entities

I implemented a function to soft-delete Content-entities, so I added a "deleted"-attribute to the Content-entity. Everything works fine.

3.) The problem

Now, when I want to create a new Container-entity, the auto-generated choices show ALL the Content-entities - even those ones, which I "marked as deleted" (delete-attribute = 1).

4.) The question

Where is the correct place to add a "filter"/"query" to only show the elements which are not marked as deleted? (delete != 1)

5.) What I've tried

a.) view/twig approach: I tried to modify the rendering of the {{ form_widget(form.contentId) }} with no success

b.) controller approach: I tried to manipulate the form-data in the newAction where the form is being created ($form = $this->createCreateForm($entity)) with no success

c.) type/buildForm approach: I tried to change the buildForm()-method ... again, no success

If would be GREAT if you could give me a hint and/or a short code example of where I could hook into the action to remove the soft-deleted choices.

Thank you very much in advance!

Answer

Nicolai Fröhlich picture Nicolai Fröhlich · May 18, 2014

You're looking for the query_builder option of the entity field.

You can create a custom query that filters the resultset in there.

example:

$builder->add('users', 'entity', array(
    'class' => 'AcmeHelloBundle:User',
    'query_builder' => function(EntityRepository $repository) {
        $qb = $repository->createQueryBuilder('u');
        // the function returns a QueryBuilder object
        return $qb
            // find all users where 'deleted' is NOT '1'
            ->where($qb->expr()->neq('u.deleted', '?1'))
            ->setParameter('1', '1')
            ->orderBy('u.username', 'ASC')
        ;
    },
));

You could go for a more general approach that filters all select statements using doctrine filters, too.