Dependency injection using Klass

It's been a while since I wanted to create a dependency injection mechanism using PHP but nerver took the time. I wanted it as simple as possible. This morning I woke up and decided it was time! So here is Klass. Only one class which other classes can extend to get their properties injected or it can be use independently. It also provides automatic getters and setters when sublclassed.

Dependency Injection (DI) is described on Wikipedia as:

Dependency Injection (DI) in computer programming refers to the process of supplying an external dependency to a software component.

Klass uses annotations for a smoother coding style. No lines of declarations needed. Just use the @Inject tag on properties where their value should be injected. Use the @Dependency tag on classes that should be injected into properties.
When using the @Inject tag, you must specify the type of the value to be injected. It can be done between parentheses after the tag or using the @var tag (see php documentor). It is also possible to change the type under which a class registers itself as a dependency. It is done the same way as with @Inject.
When the property where @Inject is used is not public, Klass will try to use a setter method.

Dependency injection can also be used on class not subclassing Klass. Using the Klass::create() method, you can create instances of any class that will profit of the injection mechanism. It is also possible to inject objects using Klass::inject(). To register an object as a dependency, use Klass::registerDependency().

class Employee extends Klass
{
    /**
     * @Inject
     * @var Boss
     */
    public $boss;
}
/** @Dependency */
class Boss extends Employee
{
}
class Freelance
{
    /** @Inject(Boss) */
    public $boss;
}

$boss = new Boss();
$employee = new Employee();
$freelance = Klass::create('Freelance');
assert($employee->boss === $boss); // true
assert($freelance->boss === $boss); // true

Klass also provides automatic generation of accessors (getters, setters, ...) for properties. This can be only done on classes subclassing Klass. Properties that should have accessors must have the @Accessors tag in their doc comment. There is three type of accessors supported: get, set and is. By default, all properties with the tag will have the get and set accessors. is is available with boolean values. It is however possible to enable only specific accessors. Specify them between parentheses and sperated by comasafter the @Accessors tag. If the property name begins with an underscore, it will be removed.

class Employee extends Klass
{
    /** @Accessors */
    protected $_name;
}

$employee = new Employee();
$employee->setName('Peter');
assert($employee->getName() == 'Peter'); // true

The @Accessors and @Inject tags can be used at the same time.

I hope this little class will help some of you. This kind of mechanism is very well suited for architecture with many components interacting between each other. I tried to comment the code as much as possible so it can be understand by anyone.

Download klass.zip (with an example) (only 4Kb)

PS: From now on, I will try (and I said try!) to post more articles. If you would like to see articles about a specific subject, don't hesitate to send an email (see the resume section).



comments powered by Disqus

21/12/2008