Search code examples
symfonysymfony-formsdqlquery-builder

Symfony form query_buider and entity repository


I'm trying to create a form with data in collection type depending on the user being logged. I'm following this chapter of the Symfony cookbook.

Everything works fine when the query_builder option is a closure where I get my data from DQL. As the data need to be fetched from different location in code, I would prefer to define the query in the Repository class.

Here is the function in my repository :

public function findOwnedBy($user) {
    $query = $this->getEntityManager()->createQuery("SELECT l FROM MyBundle:Article a JOIN a.owndBy u WHERE u.id = :userId");
    $query->setParameters(array("userId"=>$user->getId()));
    return $query->getResult();
}

This function works when called in a Controller and return an array of Article. Here is a snippet of the symfony doc :

$formOptions = array(
                    'class' => 'Acme\DemoBundle\Entity\User',
                    'multiple' => false,
                    'expanded' => false,
                    'property' => 'fullName',
                    'query_builder' => function(EntityRepository $er) use ($user) {
                        // build a custom query, or call a method on your repository (even better!)
                    },
                );

When I put a call to my Repository function in the query_builder, I get an error : Expected argument of type "Doctrine\ORM\QueryBuilder", "array" given, which I can understand because my Repository returns an array of Entity, not a QueryBuilder.

I don't want to duplicate code and create a new QueryBuilder in the Form. What is the best practice to use the query from the Repository ? I was thinking of having two function in the repository, one returning an array and the other returning the QueryBuilder, but the comment in Symfony doc "or call a method on your repository (even better!)" let me think there's better way for this case.


Solution

  • It should be easy. Do the following:

    public function queryOwnedBy($user) {
    
        $query = $this->createQueryBuilder('a')
                ->from('MyBundle:Article', 'a')
                ->innerJoin('a.owndBy', 'u')
                ->where('u.id = :id')                
                ->setParameter('id', $user->getId());
    
        return $query;
    }
    
    public function findOwnedBy($user) {
        return $this->queryOwnedBy($user)
                ->getQuery()
                ->getResult();
    }
    

    Then in the form builder:

    $formOptions = array(
        'class' => 'Acme\DemoBundle\Entity\User',
        'multiple' => false,
        'expanded' => false,
        'property' => 'fullName',
        'query_builder' => function(EntityRepository $er) use ($user) {
            return $er->queryOwnedBy($user);
        },
    );
    

    EDIT

    Thank's for ncatnow and unagi I've changed the previous functions to return the querybuilder