A simpe IoC container for PHP.
DaContainer is a powerful inversion of control container for managing class dependencies.
Simply add dagardner/dacontainer
to your composer dependencies and run composer install
.
"require": {
"dagardner/dacontainer": "1.*"
}
The last step is to include composer' s autoload file (like this: require './vendor/autoload.php'
.
And thats it. In the next chapter we we' ll cover basic usage.
DaContainer can resolve both via Closure and direct resolution. Let' s start with Closures:
$container = new \DaGardner\DaContainer\Container;
$container->bind('foo', function() {
return new stdClass;
});
$container->resolve('foo');
This will call the closure callback and therefor returns a new instance of a stdClass
.
Even if this pattern is often consired to be an anti-pattern, I implemented it, just in case somebody craves for it...
$container->singelton('foo', function() {
return new stdClass;
});
This closure is only called once during execution. The returned instance is stored and a second resolve call will return the stored instance:
($container->resolve('foo') === $container->resolve('foo));
This statement will be true.
You can also store existing objects into the container:
$object = new stdClass;
$container->instance('foo', $object);
The IoC DaContainer can also auto-inject dependencies of a class into it' s constrcutor and injector methods.
class Foo
{
public function __construct(stdClass $class) {}
public function setLogger(LoggerInterface $logger) {}
}
With some other containers this wouldn' t be possible. The DaContainer will analyze the class with Reflections and auto-inject classes.
$container->resolve('Foo');
This will just return a new instance of Foo
with a stdClass
injected into the constructor.
But how do we enable the injector method detection?
$container->enableInjecterDetection();
$container->resolve('Foo');
NOTE This feature (enableInjecterDetection()
) requires PHP 5.4 or higher. In PHP 5.3 closure to object binding is not supported, which is crucial for this feature to work.
But this won' t work right now and throws a \DaGardner\DaContainer\Exceptions\ResolveException
exception. Why?
The container doesn' t know what to do with this LoggerInterface
. Since the container doesn' t know which implementation to use you have to tell it the container!
$container->bind('LoggerInterface', 'BasicLogger');
As you can see you can also bind an id to just a class name.
If a class requires an implementation of the LoggerInterface
the container knows which implementation to use!
The Container::enableInjecterDetection()
takes as optional argument a blacklist (and the PHP_VERSION
string, but you can ignore this!)
The exact display of the method is:
\DaGardner\DaContainer\Container::enableInjecterDetection([array $blacklist = array() [, string $version = PHP_VERSION]])
The blacklist should (has to be) constructed like this:
[
'setString',
'setArray',
'_CLASSES_' => [
'SomeClass' => [
'setLogger'
]
]
]
Strings in the main array are consired to be global and are ignored everytime.
The class specific blacklist is only checked if the object is an instance of this class. A blacklist for a class should go into the _CLASSES_
key.
The algorithm of the method detection is pretty simple and not that complex. But you can write your own very algorithm.
As of version 1.3 the detection algorithm lifes in it's own class. Your detector class just has to implement an interface:
class MyDetector implements \DaGardner\DaContainer\InjectorDetection\DetectorInterface {
/**
* {@inheritdoc}
*/
public function detect(ReflectionMethod $method) { }
}
The detect(ReflectionMethod $method)
gets the method of interest passed into and the task of this class is to
return true
or false
whether the given method is a injector method.
You can inject your detector this way: $container->setDetector(new MyDetector);
. If you do not inject one the
SimpleDetector
will get used.
The IoC Container has it' s own simple event system, which can be used standalone or getting hooked into the main event dispatcher!
$container->onResolving(function($object) {
// Do something
});