DEV Community

Cover image for PHP - Auto Dependency Injection with Reflection API
F.R Michel
F.R Michel

Posted on

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!

Top comments (2)

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

indeed it must be accompanied by a caching system.