Laravel’s IoC Container and Dependency Injection decoded

Definitions and background

So what is the IoC Container?

  • Dependency Injection.
    Injecting some class into constructor is the “when to do” part (since it is called by some client). The container that should instantiate and inject the object is “what to do” part.
  • Events handling.
    Dispatching new event is the “when to do” part (since it is triggered by some client). The event listener coresponds to the “what to do” part.

What about Dependency Injection?

Inversion of control, what actually is inverted?

  1. We have client object RegisterController
  2. RegisterController is now ready to call the register method
  3. But RegisterController in order to register the user, needs to create its dependency CreateNewUserAction
  4. CreateNewUserAction will have to create the concrete dependency PostgresUser and also create instance of another dependency, the generic User model
  5. In order to hash the chosen user password, CreateNewUserAction should also call static method from BcryptHasher, which also indicates that CreateNewUserAction depends on the BcryptHasher
  1. We have client object RegisterController
  2. RegisterController has CreateNewUserAction as dependency so the IoC container will try to instantiate the CreateNewUserAction
  3. While instantiating the CreateNewUserAction, the IoC container will first need to instantiate the PostgresUser and BcryptHasher
  4. After instantiating PostgresUser and BcryptHasher is done, CreateNewUserAction is ready to be injected with its dependencies into the register method inside the RegisterController
  5. RegisterController is now ready to call register method

Replacing abstracts (interface, custom abstracts) with concrete classes

The magic behind IoC containers

Reflection Classes. The real magic

  1. Resolve the dependencies for RegisterController
  2. Resolve the dependencies for CreateNewUserAction
  3. Create new CreateNewUserAction instance with the resolved dependencies
  4. Create new RegisterController instance with the resolved dependencies (in this case CreateNewUserAction)
  5. Resolve dependencies for the register method from RegisterController
  6. Call the register method from RegisterController with the resoled dependencies

First step: Check if the given class is instantiable

  1. The container tried to resolve the UserRepository.
  2. The App\DAL\User\UserRepository is the actual value, and that is string, so the check if that is closure will return false
  3. The class already exists, so no exception is thrown
  4. But the check isInstantiable will return false, since we are trying to make instance of an interface
  5. You can see the format of the error on line :49 on the code example

Second step: Find constructor dependencies

Step three: Making instance of the concrete class

  1. Resolve the dependencies for RegisterController
  2. Resolve the dependencies for CreateNewUserAction
  3. Create new CreateNewUserAction instance with the resolved dependencies
  4. Create new RegisterController instance with the resolved dependencies (in this case CreateNewUserAction)
  5. Resolve dependencies for the register method from RegisterController
  6. Call the register method from RegisterController with the resoled dependencies

Step four: Calling the register method

PSR-11: Container interface

Summary

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Stefan Brankovikj

Stefan Brankovikj

PHP Developer since 2013. Spent most of my career working as full stack web developer, with a small turns to GoLang and Unity in my spare time