If you don't know what dependency injection, or DI, is, here is a short explanation.
Dependency injection is a way to make objects in a more organized way. Instead of using the new
keyword to create objects, you define objects you'd like to create by passing their related classes as arguments to the class constructor. In PHP, this is the __construct()
function.
When code in this class is executed, the classes we pass to the constructor are then sent to a single class that is in charge of making objects from these classes. This referred to as the "dependency injection container" class.
Object Manager is the name of the Magento class that handles how these dependencies are added. Even though we should never call the Object Manager directly in our code, this class is in charge of making and managing all of Magento's dependencies. When we give it a class, it does its magic, then gives us back an object that is an instance of that class. Then, this object is assigned back to the class property that’s mapped to it.
Benefits of DI
There are many benefits of having a single place to create all of these objects in.
First, it separates our program, so we aren’t creating objects all around the place in different parts of our code. Since all objects are created in the same place, this class also takes care of any other dependencies of that class for us. This not only makes it easier to test our code, but it also makes it less complicated.
Second, since a single class now controls how objects are made, each new object can have extra functionality added to it by the class that is creating them. This can provide these objects with some extra functionality, that would be next to impossible to do by just using the new
keyword.
Finally, dependencies can be replaced with instances of other objects at the time these objects are created. This is where Magento's crazy-powerful ability to extend shines, but is also where most of its complexity comes from. But being able to swap out these classes gives us an amazing amount of control & power.
Don’t use the "new" keyword to create objects
It’s important to know why you shouldn’t use the new
keyword to create objects in Magento.
Right now, our controller's execute()
method just returns a call to the die()
function, but that's not what we want to do. Instead, we want to send back a normal Magento page response.
It's very easy to create an object with PHP. Just use the new
keyword to name a class. Here, we are using the new
keyword to create a Session
object from Magento’s Customer
model class.
Let's use var_dump
to show this on the screen. We’ll also add an echo '<pre>'
to make the output easier to read, and call the die()
function afterwards to stop the rest of the code from running:
If we try to refresh this page though, we’ll see an ArgumentCountError
error that says:
For this Session
class to be created, we need to pass in all of its related arguments.
Let's take a look at the class of the object we are trying to create, and we'll see that this class constructor has a lot going on:
Classes are given to constructors as arguments, after which they are assigned to class properties. In Magento, we can't use the new
keyword to make an instance of this class, because it would be abnormally complex to always need to inject all of these other dependencies every time we want to create a single object.
**Create an object with dependency injection**
Instead of using Object Manager, a much better practice is to use dependency injection to create instances of objects.
This is easier than you might think, especially now that PHP 8 has promoted properties. The first thing we need to do is make a constructor.
To do this in PHP, we'll make a public function called __construct()
:
Then, we'll create a new private
property that will be passed to the constructor as an argument. This will be a Session
class instance, and the property we will assign it to will be called $session
.
When this code is executed, this class will be passed to the Object Manager class in the background, which will then create an instance of the Session
, passing the result back to the $session
property.
Specifically for this session object, it's possible that an instance of it was already created when the Magento app was first set up. There can only be one instance of the session at any given time, and the design pattern behind this concept uses what is called a “Singleton”.
In this case, since the session object was previously created, Object Manager will pass back an instance of the object that it already has. We don't have to do anything else! That's kind of cool.
Using dependency injection also means that we no longer need to import of the ObjectManager
class at the top of our files. Here’s the full implementation using DI:
This way of using dependency injection in PHP 8 is not only shorter than creating objects with Object Manager, but has less dependent classes. It no longer needs a direct reference to Object Manager, or any other classes that would otherwise be needed to create these objects with the new
keyword.
Injecting dependences in PHP 7
If you are still using PHP 7, you will need to use a different method to create and inject dependencies.
First, you'll add a new private
class property above the constructor. The name of the property will be $session
and the property's scope will be private
.
Then you will need to pass in the Session
object as an argument to the constructor, relating it back to a new $session
variable.
Finally in the constructor body, you will need to assign the $session
variable back to the private class property with $this->session
.
You’ll notice that this repeats $session
three times in the code, as opposed to the PHP 8 version that just references it a single time:
Both of these methods create the exact same result, so you can see how much Magento benefits from constructor property promotion in PHP 8.
Motivated to learn more about Magento? Consider these 3 valuable resources I have for you:
- Explore Magento 2 fundamentals & best practices course (1,000+ students)
- Grow your Magento expertise with all courses & lessons (700+ students)
- Learn visually with blocks of code & inline comments (3,000+ students)