Skip to content
Advertisement

Dependency injection on dynamically created objects

I’m using reflection to test if a class has a particular parent class and then returning an instance of it.

if (class_exists($classname)) {
     $cmd_class = new ReflectionClass($classname);
     if($cmd_class->isSubClassOf(self::$base_cmd)) {
         return $cmd_class->newInstance();
     }
} 

I want to be able to unit test these instantiated objects but I don’t know if there is any way to use dependency injection in this case. My thought was to use factories to get dependencies. Is the factory pattern the best option?

Advertisement

Answer

My thought was to use factories to get dependencies

By using this method you still would not know which dependencies a class has. I would recommend going a step further, and resolve the dependencies with the Reflection API, too.

You can actually type hint constructor arguments and the Reflection API is fully capable of reading the type hints.

Here is a very basic example:

<?php

class Email {

    public function send()
    {
        echo "Sending E-Mail";
    }

}

class ClassWithDependency {

    protected $email;

    public function __construct( Email $email )
    {
        $this->email = $email;
    }

    public function sendEmail()
    {
        $this->email->send();
    }

}


$class = new ReflectionClass('ClassWithDependency');
// Let's get all the constructor parameters
$reflectionParameters = $class->getConstructor()->getParameters();

$dependencies = [];
foreach( $reflectionParameters AS $param )
{
    // We instantiate the dependent class
    // and push it to the $dependencies array 
    $dependencies[] = $param->getClass()->newInstance();
}

// The last step is to construct our base object
// and pass in the dependencies array
$instance = $class->newInstanceArgs($dependencies);
$instance->sendEmail(); //Output: Sending E-Mail

Of course you need to do error checking by yourself (If there’s no Typehint for a constructor argument for example). Also this example does not handle nested dependencies. But you should get the basic idea.

Thinking this a step further you could even assemble a small DI-Container where you configure which instances to inject for certain Type Hints.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement