Categories


Archives


Recent Posts


Categories


Magento 2: Shared Instances and Dependency Injection

astorm

Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

If you’re being a good Magento 2 programmer, you’re not directly accessing an object manager instance. You’re using dependency injection to inject your objects in a constructor so future programmers will have a clear place to see a class’s dependencies, and change them if need be.

But we know good programmers aren’t always good developers.

Even the Magento core team sometimes dips into using an object manager instance directly, and while I wouldn’t recommend it for shipping production code, using an object manager can be much faster for prototyping new ideas or when you’re working with an unfamiliar part of the object hierarchy.

This is all covered in my Object Manager series, but its worth mentioning here again.

When you use the object manager’s get method, you’re creating a “singleton version” (sorry CS folks!) of an object, or a shared instance.

$object = $object_manager->get('FooBazModelBar'); 

Every time you use the above code, Magento will return the same FooBazModelBar object. If one part of your code sets data on this object, it will be reflected elsewhere in the system.

If you use the create method

$object = $object_manager->create('FooBazModelBar'); 

Magento will instantiate a new object, or an unshared instance i.e., roughly equivalent to

$object = new FooBazModelBar;

Understanding how DI Injects Objects

When you inject an object via automatic constructor dependency injection

public function __construct(FooBazModelBar $foo)
{
    //...
}

Magento 2, by default, uses the get method. This is “the right” thing to do from a systems point of view – less objects instantiated means better system performance. However, it can be confusing for folks thinking on the application level. These “client programmers” might not expect these objects to be shared with other parts of the system.

Automatic constructor dependency injection also supports injecting objects via create instead of get. If an object’s type is defined in a loaded di.xml file, and that object’s type includes a shared="false"

<type name="FooBazModelBar" shared="false"/>

Magento will use create when injecting the object. Generally speaking, this feels like it should be avoided. There’s zero feedback when a programmer is looking at class as to which objects may or may not be shared instances. If you need an unshared instance, its better to use the automatic factory generation features of Magento 2 to inject a factory, and then use the factory’s create method

public function __construct(FooBazModelBarFactory $factory)
{
    $this->barFactory  = $factory;
    $this->barInstance = $this->barFactory->create();
}

public function someFunction()
{
    $object = $this->barFactory->create();
}

Copyright © Alan Storm 1975 – 2017 All Rights Reserved

Originally Posted: 11th April 2016