Howto use Lazy Loading in Symfony2 (and Drupal 7 / 8)

Lazy Loading is a software design pattern which basically allows our classes and objects to be a lot lighter. Faster code, faster applications, less memory used in runtime. The great Martin Fowler says about Lazy Loading:

An object that doesn't contain all of the data you need but knows how to get it.

The key is that your "real" objects are not going to be instantiated unless they are going to be used. How that can be achieved? Easy, with what it is called a Virtual Proxy. As in every project, you can always code your own implementation, but the key about design patterns and software engineering is to reuse as much as possible. And regarding Lazy Loading, Symfony 2 has a nice implementation called Proxy Manager Bridge, which does exactly that in Symfony 2.

Recently we discovered that our implementation of Lazy Loading was not working properly in Drupal 7. We were using a custom module which we created in Capgemini, Drupal Symfony Inject, to inject our own implementations of Symfony 2 classes in Drupal. The module works great, but for some reason the Lazy Loading was not working, the objects were always having the real implementation of the object itself instead of the proxy (for more info, check the documentation in Symfony 2 about Lazy Services).

The solution is relatively easy (not as much as finding it), and I commited a patch for that, so Drupal Symfony Inject should not have that problem anymore: https://drupal.org/node/2287081.

A different question is, how to use Lazy Loading in our projects when we are not using Symfony 2 framework but its components. One of the errors which we were doing in the Drupal Symfony Inject module was that we were not loading the Proxy Manager Bridge, which makes the integration of Proxy Manager, your code and some other Symfony 2 components.

At that point we were quite lost, not many people has done before that integration between Drupal and Symfony 2 Lazy Loading, so we had very few people to ask, even inside Capgemini itself, and even fewer documentation to consult. Fortunatelly there are some interesting pieces of code in every well designed software. I am talking about test units: https://github.com/symfony/ProxyManagerBridge/blob/master/Tests/LazyProx...

The most interesting part in lines 34 and 37:

$builder->setProxyInstantiator(new RuntimeInstantiator());

That part is essential, it will instantiate the Proxy Manager and substitute your Object with an instance of that Proxy.

We just need to do one last step, indicate that our object will use Lazy Loading:

$builder->getDefinition('your_class')->setLazy(true);

From this point, the next time you load your object:

$builder->get('your_class')

if you ask for the class of this object it will identify itself as a Lazy Proxy:

\ProxyManager\Proxy\LazyLoadingInterface

That state will remain until you ask the object to return something, basically when you use one of its methods:

$your_object->doSomething();

Now that object will say that he is the real class, something like that: