Requires PHP 5.3.0 or higher.
The easiest way is to install PHP-DI with Composer.
Create a file named composer.json
in your project root:
{
"require": {
"mnapoli/php-di": "~3.5"
}
}
Then, run the following commands:
$ curl -s http://getcomposer.org/installer | php
$ php composer.phar install
If you don't use Composer, you can directly download the sources and configure it with your autoloader.
You have to define a dependency graph between your objects, which we can represent like so (nodes are objects, links are dependencies):
PHP-DI offers several ways to define dependencies, so use which ones you like.
Below is a quick introduction to some options, but you can also read the full documentation.
PHP-DI can use PHP Reflection to understand what parameters a constructor needs:
class Foo {
private $bar;
public function __construct(Bar $bar) {
return $this->bar = $bar;
}
}
PHP-DI will know that it should inject an instance of the Bar
interface or class.
No configuration needed!
Of course, this is limited to constructor injection.
You can also use annotations to define injections, here is a short example:
<?php
class Foo {
/**
* @Inject
* @var Bar
*/
protected $bar;
/**
* @Inject
*/
public function setBaz(Baz $bin) {
}
/**
* @Inject({"dbHost", "dbPort"})
*/
public function setValues($param1, $param2) {
}
}
See also the complete documentation about annotations.
$container = new Container();
// Values (not classes)
$container->set('db.host', 'localhost');
$container->set('db.port', 5000);
// Defines an instance of My\Class
$container->set('My\Class')
->withConstructor(array('db.host', 'My\Interface'));
// Mapping an interface to an implementation
$container->set('My\Interface')
->bindTo('My\Implementation');
You can define injections with a PHP array too:
<?php
return [
// Values (not classes)
'dbHost' => 'localhost',
'dbPort' => 5000,
// Class
'My\Foo' => [
'properties' => [
'bar' => 'Bar',
],
'methods' => [
'setBaz' => 'Baz',
'setValues' => ['dbHost', 'dbPort'],
],
],
];
See also the complete documentation about array configuration.
You can define injections with a YAML file too:
# Values (not classes)
dbHost: localhost
dbPort: 5000
# Class
My\Foo:
properties:
bar: Bar
methods:
setBaz: Baz
setValues: [dbHost, dbPort]
See also the complete documentation about YAML configuration.
$foo = $container->get('Foo');
But wait! Do not use this everywhere because this makes your code dependent on the container. This is an antipattern to dependency injection (it is like the service locator pattern: dependency fetching rather than injection).
So PHP-DI container should be called at the root of your application (in your Front Controller for example). To quote the Symfony docs about Dependency Injection:
You will need to get [an object] from the container at some point but this should be as few times as possible at the entry point to your application.
For this reason, we are trying to provide integration with MVC frameworks (work in progress).
To sum up:
- If you can, use
$container->get()
in you root application class or front controller - Else, use
$container->get()
in your controllers (but avoid it in your services) but keep in mind that your controllers will be dependent on the container
If you are using ZF1, PHP-DI provides easy and clean integration so that you don't have to call the container (see above about the Service Locator pattern).
First, install the bridge to ZF1:
{
"require": {
"mnapoli/php-di": "The version you want here",
"mnapoli/php-di-zf1": "*"
}
}
To use PHP-DI in your ZF1 application, you need to change the Dispatcher used by the Front Controller in the Bootstrap.
protected function _initDependencyInjection() {
$container = new \DI\Container();
$dispatcher = new \DI\ZendFramework1\Dispatcher();
$dispatcher->setContainer($container);
Zend_Controller_Front::getInstance()->setDispatcher($dispatcher);
}
That's it!
Now you have dependency injection in your controllers.
Warning: if you use Zend's autoloader (and not Composer), you will need to configure it:
$autoloader->suppressNotFoundWarnings(true);
Read more on the PHP-DI-ZF1 project on Github.