Doctrine2 (Doctrine 2.1) eager loading in Symfony2

Guillaume Flandre picture Guillaume Flandre · Jan 12, 2012 · Viewed 15.1k times · Source

Let's say I have two entities in my Symfony2 project : Category and Article (a category having many articles).

In my CategoryRepository, I have this method:

findAllDummy(){
  return $this->createQueryBuilder('c')
              ->leftJoin('c.Articles a')
              ->getQuery()->getResult();
}

If I remember well, in Symfony1.4 (and the corresponding version of Doctrine), the returned objects would have their 'articles' attribute filled by the corresponding Article objects. Now, in Symfony2, Proxy objects are returned.

So if I loop through a specific category's articles, As many queries as iterations will be executed.

foreach($category->getArticles() as $article){
  echo $article->getDoctrine()
               ->getRepository('')getTitle();
}

I understand this is Doctrine2.1's default lazy loading behavior.

Question 1: how is this a better solution? N queries instead of 1.

I tried to force eager loading by doing the following:

findAllDummy(){
  return $this->createQueryBuilder('c')
              ->leftJoin('c.articles a')
              ->getQuery()
              ->setFetchMode('Category', 'articles', 'EAGER')
              ->getResult();
}

But the result remains the same.

Question 2: how to force eager loading in Doctrine2?

Answer

Crozin picture Crozin · Jan 12, 2012

You're joining a table but you're not selecting anything from it. Add ->addSelect('a') to your query builder. Consider two following SQL queries to understand the difference:

SELECT a.id, a.title
FROM article a 
JOIN category c ON a.category_id = c.id 
WHERE a.id = 123;

SELECT a.id, a.title, c.id, c.name 
FROM article a 
JOIN category c ON a.category_id = c.id 
WHERE a.id = 123;

Eager/lazy joining has nothing to do with DQL queries. It defines what should be loaded when you use $articleRepository->find(123).