Dependency Injection
Inversion is a simple and functional dependency injection container for PHP 5.3. Supports Service Oriented Architecture, Links, PRS-0, and Composer .

You can install it through packagist.org: granula / inversion or by downloading and adding a compatible bootloader to PRS-0.
The above example shows the basic functionality of a container. Let's see what happens there.
In the first line we create an instance of the container. In the second, we create an association between "foo" and the service creating an instance of the class "My \ Class \ Foo". What else can be written like this:
In the third line we get an instance of the object. What else can be written like this:
By default, when a string is passed to the container, it is understood as the class name and is substituted into the Inversion \ Servise service.
This service has several features and functions.
The first is delayed loading. Until you use it, the class will not be loaded.
Second, you can specify a dependency on other services and parameters. I will explain with an example.
Suppose we have the Bar class, which depends on the One and Two classes:
We describe this dependency in Inversion:
Now when you call bar, they will be created and substituted into the constructor. Actually it can be even easier. If instead of “one” and “two” indicate their class names:
This is a convenient way to describe dependencies when using interfaces:
In general, the names of the interfaces can be omitted. They will be automatically obtained from the classes:
Just like that.
There are several services in the library, however you can create your own by implementing Inversion \ ServiceInterface .
Class: Inversion \ Service \ Closure
Usage:
You can also specify dependencies:
As with Inversion \ Service, you can specify them explicitly:
Class: Inversion \ Service \ Factory
Use:
You can also specify dependencies for the constructor explicitly as the third parameter.
Class: Inversion \ Service \ Object
Usage:
or
Class: Inversion \ Service \ Prototype
Use:
Each call will create a new copy: clone $ object.
Class: Inversion \ Service \ Data
Usage:
By default, all arrays are converted to Data services.
Equivalent to:
Inversion supports links. To get the link, refer to the container as an array:
Thus, you can create an alias to any service:
Now if someone rewrites “My \ Class \ FooInterface”, then “foo” will still refer to this service:
You can even create links to links:
For example, if we want to expand some service, then this method will not work. he will overwrite the first one:
As a result, there will be a loop to avoid this, use the following function to expand:
The Inversion library is fully tested. Tests are located in a separate repository ( granula / test ) to reduce the size of the library.
Inversion is designed completely without the use of static methods and singleton, however it is rarely useful to have a container like a singleton:

You can install it through packagist.org: granula / inversion or by downloading and adding a compatible bootloader to PRS-0.
$container = new Inversion\Container();
$container['foo'] = 'My\Class\Foo';
// ...
$foo = $container('foo');
The above example shows the basic functionality of a container. Let's see what happens there.
In the first line we create an instance of the container. In the second, we create an association between "foo" and the service creating an instance of the class "My \ Class \ Foo". What else can be written like this:
$container->addService(new Service('My\Class\Foo'), 'foo');
The name “foo” comes second, as it can be omitted altogether. More details below.
In the third line we get an instance of the object. What else can be written like this:
$foo = $container('foo');
// или
$foo = $container->get('foo');
// или
$foo = $container['foo']->get();
// или
$foo = $container->getService('foo')->get();
However, I recommend using the shortened version, although all of them are valid.
Dependency Description
By default, when a string is passed to the container, it is understood as the class name and is substituted into the Inversion \ Servise service.
This service has several features and functions.
The first is delayed loading. Until you use it, the class will not be loaded.
Second, you can specify a dependency on other services and parameters. I will explain with an example.
Suppose we have the Bar class, which depends on the One and Two classes:
namespaceMy\Space;
classOne{}
classTwo{}
classBar{
publicfunction__construct(One $one, Two $two){
}
}
We describe this dependency in Inversion:
useInversion\Service;
//...
$container['one'] = 'My\Space\One';
$container['two'] = 'My\Space\Two';
$container['bar'] = new Service('My\Space\Bar', array($container['one'], $container['two']));
Now when you call bar, they will be created and substituted into the constructor. Actually it can be even easier. If instead of “one” and “two” indicate their class names:
$container['My\Space\One'] = 'My\Space\One';
$container['My\Space\Two'] = 'My\Space\Two';
$container['My\Space\Bar'] = new Service('My\Space\Bar'); // "new Service" можно опустить
This is a convenient way to describe dependencies when using interfaces:
namespaceMy\Space;
classOneimplementsOneInterface{}
classTwoimplementsTwoInterface{}
classBarimplementsBarInterface{
publicfunction__construct(OneInterface $one, TwoInterface $two){
}
}
$container['My\Space\OneInterface'] = 'My\Space\One';
$container['My\Space\TwoInterface'] = 'My\Space\Two';
$container['My\Space\BarInterface'] = 'My\Space\Bar';
In general, the names of the interfaces can be omitted. They will be automatically obtained from the classes:
$container[] = 'My\Space\One';
$container[] = 'My\Space\Two';
$container[] = 'My\Space\Bar';
Just like that.
However, you need to understand that in this case, the classes will be immediately loaded to get a list of interfaces through reflection. Therefore, it is better to specify the interface name manually.
Other types of services
There are several services in the library, however you can create your own by implementing Inversion \ ServiceInterface .
Closure
Class: Inversion \ Service \ Closure
Usage:
$container['closure'] = function()use($container){
returnnew My\Class();
};
You can also specify dependencies:
$container['closure'] = function(One $foo, Two $foo)use($container){
returnnew My\Class();
};
As with Inversion \ Service, you can specify them explicitly:
$container['closure'] = new Closure(function(One $foo, Two $foo)use($container){
returnnew My\Class();
}, array($container['one'], $container['two']));
Factory
Class: Inversion \ Service \ Factory
Use:
$container['factory'] = new Factory('My\ClassFactory', 'create');
You can also specify dependencies for the constructor explicitly as the third parameter.
Object
Class: Inversion \ Service \ Object
Usage:
$container['object'] = new My\Class();
or
$container['object'] = new Object(new My\Class());
Prototype
Class: Inversion \ Service \ Prototype
Use:
$container['prototype'] = new Prototype($object);
Each call will create a new copy: clone $ object.
Data
Class: Inversion \ Service \ Data
Usage:
$container['data'] = new Data('what you want');
By default, all arrays are converted to Data services.
$container['data'] = array(...);
Equivalent to:
$container['data'] = new Data(array(...));
Service Links
Inversion supports links. To get the link, refer to the container as an array:
$container['foo'] = new Service(...);
$ref = $container['foo']; // Ссылка на сервис.
Thus, you can create an alias to any service:
$container['My\Class\FooInterface'] = new Service('My\Class\Foo');
$container['foo'] = $container['My\Class\FooInterface'];
//...
$foo = $container('foo');
Now if someone rewrites “My \ Class \ FooInterface”, then “foo” will still refer to this service:
//...
$container['My\Class\FooInterface'] = new Service('Another\FooImpl');
//...
$foo = $container('foo'); // $foo instanseof Another\FooImpl
You can even create links to links:
$container['foo'] = 'My\Class\Foo';
$container['ref'] = $container['foo'];
$container['ref2'] = $container['ref'];
$container['ref3'] = $container['ref2'];
//...
$foo = $container('ref3'); // $foo instanseof My\Class\Foo
$name = $container->getRealName('ref3'); // $name == 'foo'
Service extension
For example, if we want to expand some service, then this method will not work. he will overwrite the first one:
$container['My\Class\FooInterface'] = 'My\Class\Foo';
//...
$container['My\Class\FooInterface'] = function(FooInterface $foo){
$foo->extendSome(...);
return $foo;
};
As a result, there will be a loop to avoid this, use the following function to expand:
$container['My\Class\FooInterface'] = 'My\Class\Foo';
//...
$container->extend('My\Class\FooInterface', function(FooInterface $foo){
returnnew FooDecorator($foo);
});
Tests
The Inversion library is fully tested. Tests are located in a separate repository ( granula / test ) to reduce the size of the library.
Like Singleton
Inversion is designed completely without the use of static methods and singleton, however it is rarely useful to have a container like a singleton:
$container = Inversion\Container::getInstanse();
Other implementations
- Symfony Dependency Injection is a powerful and heavy dependency injection library. Has good documentation.
- Pimple is a simple and very lightweight (just one file) “container” from the creator of Symfony.