Page 1 of 1

ConstructorInjector [PHP5.1.3+]

Posted: Tue Sep 12, 2006 8:20 pm
by Jenk
After the discussions in T+D I came up with this:

Code: Select all

class ConstructorInjector
{
    public static $instance;
    private $_components;
    
    private function __construct()
    {
        $this->components = array();
    }
    
    public static function getInstance()
    {
        if (!(self::$instance instanceof self)) self::$instance = new self;
        
        return self::$instance;
    }
    
    public function addComponent($class)
    {
        if (!class_exists($class))
        {
            throw new InvalidArgumentException('Class ' . $class . ' has not been defined.');
        }
        else
        {
            $this->_components[$class] = array();
            $object = new ReflectionClass($class);
            $params = $object->getConstructor()->getParameters();

            foreach ($params as $param)
            {
                if ($var = $param->getClass())
                {
                    $this->_components[$class][] = $var->getName();
                }
            }
        }
    }
    
    public function instantiateObject($class)
    {
        if (!isset($this->_components[$class]))
        {
            try
            {
                $this->addComponent($class);
            }
            catch (Exception $e)
            {
                throw $e;
            }
        }
        
        $args = array();
        foreach ($this->_components[$class] as $comp)
        {
            $args[] = $this->instantiateObject($comp);
        }
        
        $reflect = new ReflectionClass($class);
        return $reflect->newInstanceArgs($args);
    }
}
Tis not perfect, hence it being in here (or perhaps should be T+D?). :)

First thing on my TODO is add a check for the dependency being an instance or class, and for __constructor() because if any of the dependencies don't have one, the injector dies :P

I didn't create a full unit-test for this, however it's pretty easy to see the test I did:

Code: Select all

<?php

include 'ConstructorInjector.php';

class Bar {}

class Foo
    public $bar;

    public constructor(Bar $bar)
    {
        $this->bar = $bar;
    }
}

$in = ConstructorInjector::getInstance();

$foo = $in->instantiateObject('Foo');

echo get_class($foo->bar); // outputs 'Bar'

?>
Anywho.. time for sleep at last.

N.B. 5.1.3+ because of the use of ReflectionClass::newInstanceArgs()