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!
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.
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:
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.
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.
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.
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
If we already have an instance of a class and we want to register it in the container, we can do so using the
$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.
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!