• Home
  • blog
  • How to Build Your Own Dependency Injection Container

How to Build Your Own Dependency Injection Container

A search for “dependency injection container” on packagist currently provides over 95 pages of results. It is safe to say that this particular “wheel” has been invented.

Square wheel?

However, no chef ever learned to cook using only ready meals. Likewise, no developer ever learned programming using only “ready code”.

In this article, we are going to learn how to make a simple dependency injection container package. All of the code written in this article, plus PHPDoc annotations and unit tests with 100% coverage is available at this GitHub repository. It is also listed on Packagist.

Planning Our Dependency Injection Container

Let us start by planning what it is that we want our container to do. A good start is to split “Dependency Injection Container” into two roles, “Dependency Injection” and “Container”.

The two most common methods for accomplishing dependency injection is through constructor injection or setter injection. That is, passing class dependencies through constructor arguments or method calls. If our container is going to be able to instantiate and contain services, it needs to be able to do both of these.

To be a container, it has to be able to store and retrieve instances of services. This is quite a trivial task compared to creating the services, but it is still worth some consideration. The container-interop package provides a set of interfaces that containers can implement. The primary interface is the ContainerInterface that defines two methods, one for retrieving a service and one for testing if a service has been defined.

interface ContainerInterface
    public function get($id);
    public function has($id);

Learning From Other Dependency Injection Containers

The Symfony Dependency Injection Container allows us to define services in a variety of different ways. In YAML, the configuration for a container might look like this:

    # ...
    mailer.transport: sendmail

        class:     Mailer
        arguments: ["%mailer.transport%"]
        class:     NewsletterManager
            - [setMailer, ["@mailer"]]

Continue reading %How to Build Your Own Dependency Injection Container%