DEV Community

loading...
Cover image for PHP - Auto Dependency Injection with Reflection API

PHP - Auto Dependency Injection with Reflection API

fadymr profile image F.R Michel ・1 min read

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!

Discussion (2)

pic
Editor guide
Collapse
carlosas profile image
Carlos Alandete Sastre

Just be careful while using Reflection in production apps. It affects performance.

Collapse
fadymr profile image
F.R Michel Author

indeed it must be accompanied by a caching system.