Doctrine Extra Lazy Associations


In this video we look at how we can make use of Extra Lazy Associations inside our Doctrine Entities to reduce query overhead.

Simply put, marking something as Lazy in computing terms means to delay the computation of that particular thing until required.

A simple way of thinking about this would be to think of two very large numbers, and then wonder what the end result of adding those two numbers together would be. If you're sat in your pants on the sofa, you have no urgent requirement to figure out what that number is, so you delay it / decide not to bother doing it. The lazy way.

But then, what if adding those two numbers up suddenly meant something to you. What if adding those two together would guarantee you a million pounds GBP. What? I like money, I can do maths, let's put these things together and make some money.

So you add them up. And it turns out it was all a big lie and there's no money. Well, that's a different issue. But the end result is - you delayed doing something until it mattered. You were lazy.

Doctrine provides us with something similar. And it's free out of the box. Whenever we have an association - a collection of related entities - that collection is marked as Lazy.

Doctrine won't actually go ahead and populate that Collection Object until you first access it. Behind the scenes / by default, that association has been given the configuration: fetch="LAZY" - it's free, we don't need to annotate this, but if we did, it would look like this:

    /**
     * @ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="LAZY")
     */
    public $users;

But we don't.

Lazy associations won't trigger a Collection load for add or offsetSet - see the manual page for more details on this.

Not triggering on add may be not what you're after. Sometimes you don't want to add the same thing to a collection more than once. That's why you might have seen code like this:

if ( ! $myCollection->contains($blah) {
  $myCollection->add($blah);
}

Extra Lazy Associations expand on this.

We get some additional methods that won't trigger a full collection load: contains, containsKey, count, get, and slice.

Be sure to check the manual on these as they aren't all available in Doctrine 2.4 which current ships with a standard Symfony install (composer show -i to see which Doctrine version you are using).

In the video we will go over the count method, and see what this ends up giving us.

The upshot is, we don't reduce our number of queries, but we do reduce the query overhead.

Adding Extra Lazy Associations to our entities is super easy, and crucially, doesn't require schema updates.

If we take the above example (which is straight from the Doctrine docs), all we need to change is the value of our fetch annotation parameter, and we are good to go:

    /**
     * @ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="EXTRA_LAZY")
     */
    public $users;

Quick and easy.

Additional Reading

Code For This Course

Get the code for this course.

Episodes