
- General
Dependency Injection
Dependency Injection
What is dependency injection?
To understand dependency injection first we need to know about dependency. Let’s take an example.
Class User {
Private Profile $profile;
Public user(){
$this.profile = new Profile();
}
}
Here we have a class User. which has another class Profile object as variable. So We can say that user class is dependent on profile class. In this example user class has a constructor which is creating object of profile class.
Dependency injection is a technique whereby one object supplies the dependencies of another object.
Now just modify above example like that –
Class User {
Private Profile $profile;
Public user(Profile $profile){
$this.profile = $profile;
}
}
Here User class is dependent on Profile class. But it is not instantiate profile object itself. It just out source dependency and when ever we will instantiate user class we need to instantiate profile class also.
Like this –
$profile = new Profile();
$user = new User($profile);
Type of dependency injection
- By Constructor – In this type we pass or inject dependency by constructor. like our example.
- By Setter method – In this type we pass dependency to setter method. For example –
Class User {
Private Profile $profile;
Public setProfile(Profile $profile){
$this.profile = $profile;
}
}
Here we are passing dependency by setter method.
$user = new User();
$user->setProfile(new Profile());
This is how we pass it.
Dependency Injection Container
In our examples we are resolving dependencies manually. What if our application automatically handle the dependencies for a specific class instead of doing it manually.
DI container is a class or application who resolve dependencies automatically.
Look at a DI container below:
<?php
/**
* Class Container
*/
class Container
{
/**
* @var array
*/
protected $instances = [];
/**
* @param $abstract
* @param null $concrete
*/
public function set($abstract, $concrete = NULL)
{
if ($concrete === NULL) {
$concrete = $abstract;
}
$this->instances[$abstract] = $concrete;
}
/**
* @param $abstract
* @param array $parameters
*
* @return mixed|null|object
* @throws Exception
*/
public function get($abstract, $parameters = [])
{
// if we don't have it, just register it
if (!isset($this->instances[$abstract])) {
$this->set($abstract);
}
return $this->resolve($this->instances[$abstract], $parameters);
}
/**
* resolve single
*
* @param $concrete
* @param $parameters
*
* @return mixed|object
* @throws Exception
*/
public function resolve($concrete, $parameters)
{
if ($concrete instanceof Closure) {
return $concrete($this, $parameters);
}
$reflector = new ReflectionClass($concrete);
// check if class is instantiable
if (!$reflector->isInstantiable()) {
throw new Exception("Class {$concrete} is not instantiable");
}
// get class constructor
$constructor = $reflector->getConstructor();
if (is_null($constructor)) {
// get new instance from class
return $reflector->newInstance();
}
// get constructor params
$parameters = $constructor->getParameters();
$dependencies = $this->getDependencies($parameters);
// get new instance with dependencies resolved
return $reflector->newInstanceArgs($dependencies);
}
/**
* get all dependencies resolved
*
* @param $parameters
*
* @return array
* @throws Exception
*/
public function getDependencies($parameters)
{
$dependencies = [];
foreach ($parameters as $parameter) {
// get the type hinted class
$dependency = $parameter->getClass();
if ($dependency === NULL) {
// check if default value for a parameter is available
if ($parameter->isDefaultValueAvailable()) {
// get default value of parameter
$dependencies[] = $parameter->getDefaultValue();
} else {
throw new Exception("Can not resolve class dependency {$parameter->name}");
}
} else {
// get dependency resolved
$dependencies[] = $this->get($dependency->name);
}
}
return $dependencies;
}
}
This container is registering each class via set method.
$container = new Container();
$container->set(“User”);
Whenever we want to instantiate User we need to call get method of container.
$user = $container->get(“User”);
get() function is going through resolve() function, which is checking if the User class has any dependencies via its __construct() so it will resolve them recursively (means if Profile class has dependencies, they will be resolved as well), otherwise, it will instantiate User class direct.
DI container use ReflectionClass. The ReflectionClass class reports information about a class. You can read about it here.
Conclusion – Dependency Injection is passing of dependency to object. To do it manually we need to use a DI container. Who will Autowired the dependency for application.
Related content
Auriga: Leveling Up for Enterprise Growth!
Auriga’s journey began in 2010 crafting products for India’s [...]
Stay Close to What We’re Building
Get insights on product engineering, AI, and real-world technology decisions shaping modern businesses.






