Dependency Injection in Mako Framework for PHP
Tags: php, webdev, beginners, tutorial
Published: 2023-07-29 20:57:01

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:

```php
$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.

```php
$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.

```php
$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:

```php
$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.

```php
$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.

```php
$engine = $container->get(EngineInterface::class);
```

Or using the optional key:

```php
$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!