Thomas Portelange
LeKoala Dev Blog


LeKoala Dev Blog

Creating a Dependency Injection (DI) Container

Creating a Dependency Injection (DI) Container

Thomas Portelange's photo
Thomas Portelange
·Sep 15, 2021·

2 min read

A while ago, I've created a small PHP framework. In order to adhere to modern practice (it even has basic middleware support even if I don't like them), I had to pick a DI container. The issue was: either there were too complicated, or too simple. And also, sometimes I like to reinvent the wheel.

But what is a DI container exactly?

To make it simple, a DI container is a class used to instantiate other classes based on definitions. An interface has been defined in the PSR-11 about Container interface.

Why create my own

To be honest, it wasn't really the plan. I found out devanych/di-container and I was really impressed by the simplicity of it. But there were a few things I wanted to improve.

First, I wanted the DI container to fit in one single class. In order to do that, I had to convert the Exceptions to anonymous classes extending the base PSR interface.

And then, there were a couple of other features I wanted to have:

  • Picking dependency by name if they returned the proper type
  • Allow overriding distinct parameters
  • Call methods after instantiation (not everything can be set in the constructor)

Actually, I managed to fit all that under 300 LOC so I'm quite happy with the result. Of course, it's not as featured as PHP-DI or the Symfony DI component, but if 300 LOC do the job, why use more?

What is a minimalist container?

I had a discussion today on Reddit about Capsule 3 that was recently released. The package shared a lot of my own goals:

  • No cache (because it shouldn't be necessary)
  • PHP configuration (no yml, special syntax, etc)
  • Predictable output (always return the same instance once loaded)

But there was one key difference: it uses a Definition object instead of a plain array. While this may seem like an improvement, it's not perfect in my opinion:

  • It makes the package more complicated than needed (and you need to test it)
  • At the end of the day, you end up passing "magic" key/values to the argument method anyway, so it's not like the definition object help you to pick the right value (at least, a real config object would allow typed settings).

So... arrays it is for me.


Well, I'm not sure where I'm going with this article :-) hopefully you picked some interesting stuff or it helped you think differently about the topic.

If you want to learn more about my approach, you can also read the docs

Share this