Search code examples
phpsymfonydoctrine-ormdoctrineentities

Doctrine2 Lazy Loading


I was reading about lazy associations in Doctrine 2 and how I could avoid the following situation:

Entity dump in twig template

In this paragraph in the documentation is explained how to enable lazy associations for your entity. I am missing how I could use this within my entity repository.

So far I tried some adjustments to the entity repository but without any success. I also tried this post, this post and this post but they seem to handle ManyToMany or a complete other situation.

Could somebody explain how and where to use lazy association to avoid the above example?

Irrelevant private properties and getters/setters have been removed from this code snippets due to the length.

src/AppBundle/Entity/News.php

class News
{
    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Account", fetch="EXTRA_LAZY")
     * @ORM\JoinColumn(name="author", referencedColumnName="id")
     */
    private $author;
}

src/AppBundle/Entity/Repositories/NewsRepository.php

class NewsRepository extends EntityRepository
{
    /**
     * @param $id
     * @return mixed
     * @throws \Doctrine\ORM\NonUniqueResultException
     */
    public function findOneById($id) {
        return $this->createQueryBuilder('a')
                    ->andWhere('a.id = :id')
                    ->setParameter('id', $id)
                    ->getQuery()
                    ->getOneOrNullResult();
    }
}

src/AppBundle/Controller/NewsController.php

/**
 * @Route("/{id}", name="news_item")
 * @Method({"GET"})
 * @Template("AppBundle:news:item.html.twig")
 */
public function articleAction(Request $request, $id)
{
    $news_item = $this->getDoctrine()->getRepository('AppBundle:News')->findOneById($id);

    if (!$news_item) {
        throw $this->createNotFoundException('No news item found by id ' . $id);
    }

    return array(
        'news_item' => $news_item
    );
}

src/AppBundle/Resources/views/news/item.html.twig

{% extends 'base.html.twig' %}

{% block body %}
    {{ dump(news_item) }} }}
{% endblock %}

Solution

  • You don't have to do anything special to enable lazy loading. Extra lazy loading in the relationship you show isn't necessary for News to not load an Author. It just means you can make calls like ->contains on a collection without loading the entire collection & a few other conveniences.

    dump() should show something on Author like:

    protected 'author' => 
        object(Proxies\__CG__\YourNamespace\YourBundle\Entity\Author)
    

    This doesn't mean the entity has been fetched from the db. To quote the docs.

    Instead of passing you back a real Author instance and a collection of comments Doctrine will create proxy instances for you. Only if you access these proxies for the first time they will go through the EntityManager and load their state from the database.

    If you don't get back a proxy class, it's probably because you've already accessed that relationship earlier in your code. Or you've explicitly fetched that entity in your query.