1
votes

Using Symfony 2.8.

I have Community and MenuItem entities, where a Community has a set of MenuItems.

Community.php has the following code:

...
    /**
     * @ORM\OneToMany(targetEntity="MenuItem", mappedBy="community", fetch="LAZY")
     * @ORM\OrderBy({"sequence" = "ASC"})
     */
    private $menuItems;
...

MenuItem.php has the following code:

...
    /**
     * @var Community
     *
     * @ORM\ManyToOne(targetEntity="Community", inversedBy="menuItems")
     */
    private $community;
...

The point is, when I use:

$menuItems = $community->getMenuItems();

the $menuItems variable will be an empty collection.

The problem can be solved by setting fetch="EAGER" instead of fetch="LAZY", because in that way the $menuItems attribute of the Category entity is loaded immediatly.

LAZY vs EAGER (source) :

Whenever you have a managed entity instance at hand, you can traverse and use any associations of that entity that are configured LAZY as if they were in-memory already. Doctrine will automatically load the associated objects on demand through the concept of lazy-loading.

Whenever you query for an entity that has persistent associations and these associations are mapped as EAGER, they will automatically be loaded together with the entity being queried and is thus immediately available to your application.

The point is that while EAGER loading is working as expected, LAZY loading seems not working at all. Any idea about why?

3

3 Answers

1
votes

When you are doing $community->getMenuItems(); :

  • In EAGER mode: the data are already fetched, so the array is returned.
  • In LAZY mode: the database request is done when you do the call. Behind the scene it works by generating "proxies" in front of your entities that will call doctrine for you.

Carefull with lazy loading :

Traversing the object graph for parts that are lazy-loaded will easily trigger lots of SQL queries and will perform badly if used to heavily.

It's better to fetch directly the data, by doing a DQL fetch. See for instance http://blog.bemycto.com/good-practices/2015-05-31/understanding-doctrine-orm-lazy-load-fetch-join/

1
votes

This seems to work to load the lazy relationship.

$logs = $entity->getLogs(); // lazy relationship
$this->getDoctrine()->getManager()->initializeObject($logs);

$logs will now populate.

Docs for initializeObject:

Helper method to initialize a lazy loading proxy or persistent collection.

0
votes

Personally, I'm not a fan of lazy/eager loading as many queries will be fired when they can be done in one query with joins.

Please see my answer here on how to implement a custom repository to build a custom query, link