Dependency injection is so important in the architecture of your PHP app. When you start out with a tiny project, it's workable without it. When that project gets bigger, oh man! So let's go over Dependency Injection in the Mako Framework!
Understanding Dependency Injection
Let's say we have a Car
class and this class needs an instance of an Engine
class to work. Instead of creating an instance of the Engine
class inside the Car
class, we "inject" the Engine
instance into the Car
when we create it. This is the core idea of Dependency Injection.
Registering a Dependency
In Mako, we can register these dependencies in a container. The container is a special object that holds and manages instances of our classes. When we register a dependency, we're telling the container how to create an instance of a certain class.
Here's an example of how to register a dependency:
$container->register(EngineInterface::class, Engine::class);
In this case, EngineInterface::class
is the key we use to refer to the dependency in the container, and Engine::class
is the concrete class that will be instantiated when we ask the container for this dependency.
Registering a Dependency with a Key
We can also associate a key with our dependency. This can make our code easier to read and write, and it also allows us to access our dependencies in a more flexible way.
$container->register([EngineInterface::class, 'engine'], Engine::class);
In this example, we're associating the key 'engine' with our Engine::class
dependency. Now we can retrieve our Engine
instance from the container using either EngineInterface::class
or 'engine' as the key.
Registering a Dependency with a Closure
Sometimes, creating an instance of a class might involve some complex logic or additional configuration. In these cases, we can use a closure to define how the instance should be created.
$container->register([WheelInterface::class, 'wheel'], fn ($container) => new Wheel('parameter value'));
Here, we're telling the container to create a new instance of Wheel
with 'parameter value' as an argument. The closure gives us a lot of flexibility when it comes to creating our instances.
Registering a Singleton Dependency
Sometimes, we want to ensure that there's only one instance of a certain class in our application. There are times like when you only want one guaranteed instance of a Database Connection no matter how many times you call a service from a container. This is known as a singleton. We can register a singleton dependency in the container like this:
$container->registerSingleton([EngineInterface::class, 'engine'], fn ($container) => new Engine('parameter value'));
Now, every time we ask the container for the 'engine' dependency, it will always return the same instance of Engine
.
Registering an Existing Instance
If we already have an instance of a class and we want to register it in the container, we can do so using the registerInstance
method.
$container->registerInstance([WheelInterface::class, 'wheel'], new Wheel('parameter value'));
This can be useful if we need to register an instance that was created outside of the container, or if we want to share a specific instance across different parts of our application.
Resolving a Dependency
Once we've registered our dependencies in the container, we can retrieve them using the get
method. This is known as resolving a dependency.
$engine = $container->get(EngineInterface::class);
Or using the optional key:
$engine = $container->get('engine');
When we resolve a dependency, the container will give us an instance of the class associated with the given key. If the dependency was registered with a closure, the container will execute the closure to create the instance.
And that's it! You now know how to add a new dependency to the application container using the Mako PHP framework. Remember, the key to understanding Dependency Injection is practice, so don't hesitate to experiment with these concepts in your own projects. Happy coding!
Top comments (0)