PHP - Auto Dependency Injection with Reflection API

fadymr

F.R Michel

Posted on January 30, 2021

PHP - Auto Dependency Injection with Reflection API

Resolve the dependencies of our objects

We're going to use the Reflection API

We Instantiating an object with its dependencies :

<?php
class MainController {

    /**
     * @var UserRepository
     */
    private $repository;

    public function __construct(UserRepository $repository)
    {
        $this->repository = $repository;
    }
}
class UserRepository {

    /**
     * @var Database
     */
    private $database;

    public function __construct(Database $database)
    {
        $this->database = $database;
    }
}

class Database {
}

$controller = new MainController(new UserRepository(new Database()));
Enter fullscreen mode Exit fullscreen mode

The dependencies has dependencies themselves and this can become unmanageable

The solution :

<?php

class ReflectionResolver
{
    /**
     * @param string $class
     * @return object
     * @throws \ReflectionException
     */
    public function resolve(string $class): object
    {
        $reflectionClass = new \ReflectionClass($class);

        if (($constructor = $reflectionClass->getConstructor()) === null) {
            return $reflectionClass->newInstance();
        }

        if (($params = $constructor->getParameters()) === []) {
            return $reflectionClass->newInstance();
        }

        $newInstanceParams = [];
        foreach ($params as $param) {
            $newInstanceParams[] = $param->getClass() === null ? $param->getDefaultValue() : $this->resolve(
                $param->getClass()->getName()
            );
        }

        return $reflectionClass->newInstanceArgs(
            $newInstanceParams
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

How to use ?

<?php
$resolver = new ReflectionResolver();
$controller = $resolver->resolve(MainController::class)
var_dump($controller);
//object(MainController)[1]
//  private 'repository' => 
//    object(UserRepository)[2]
//      private 'database' => 
//        object(Database)[3]
Enter fullscreen mode Exit fullscreen mode

Ideal for small project
Simple and easy!

💖 💪 🙅 🚩
fadymr
F.R Michel

Posted on January 30, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related