m0rtis / simple-box
Simple PSR-11 container with optional autowiring
Requires
- php: ^7.2
- psr/container: ^1.0
Requires (Dev)
- m0rtis/picklock: ^1.0
- phpunit/phpunit: ^7.0
- roave/security-advisories: dev-master
- squizlabs/php_codesniffer: ^3.0
Provides
This package is auto-updated.
Last update: 2024-10-19 09:51:08 UTC
README
Simple and little PSR-11 dependency injection container with optional autowiring. This package contains only 4 files, 2 of which implement exception interfaces required by PSR-11.
Installing
The best way is to install this package via composer:
composer require m0rtis/simplebox
Usage
Basic
If you don't need autowiring you should to use m0rtis\SimpleBox\Container
class in your application.
use m0rtis\SimpleBox\Container
$container = new Container([$arrayOrIteratorWithYourData]);
But if you want to use autowiring please feel free to instantiate m0rtis\SimpleBox\AutowiringContainer
class which extends the basic container class.
use m0rtis\SimpleBox\AutowiringContainer
$container = new AutowiringContainer([$arrayOrIteratorWithYourData]);
If you are using autowiring container you can get any existent (class_exists === true
) class even if you didn't put it to container before! Just request it by class name and AutowiringContainer will try make an instance for you. We recommend to check if container can instantiate an object for you using PSR-11 has
method:
if ($autowiringContainer->has(RequiredClass::class) {
$object = $autowiringContainer->get(RequiredClass::class);
}
Please note that SimpleBox container implements ArrayAccess interface. It means you can use SimpleBox container like an array:
if (isset($autowiringContainer[RequiredClass::class])) {
$object = $autowiringContainer[RequiredClass::class];
}
Configuration
There is no any separate storage in SimpleBox for configuration. SimpleBox container looks for configuration by item id config
. This item is expected to be an array or iterable.
The configuration related to a particular class must be placed under the key with the name of this class or one of the interfaces that it implements.
For example, we have a class:
class SomeAwesomeClass implements AwesomeInterface
{
private $config;
public function __construct (iterable $config)
{
$this->config = $config;
}
}
As you can see it requires some config for instantiation (name of argument MUST be exactly config
). So you should to place config for it this way:
$container = new AutowiringContainer([
'config' => [
SomeAwesomeClass::class => [
'configKey' => 'configValue'
]
]
]);
or this way:
$container = new AutowiringContainer([
'config' => [
AwesomeInterface::class => [
'configKey' => 'configValue'
]
]
]);
In both cases when you will query SomeAwesomeClass
from autowiring container requested class will be instantiated with
his own config:
$config = ['configKey => 'configValue']
SimpleBox container itself has the only config option now - return_shared
.
This is a flag that indicates whether the container will return the same object with the same queries or create a new object each time. Default behavior is to return the same object. You can see example in our tests:
$result1 = $container->get(DependencyTwo::class);
$result2 = $container->get(DependencyTwo::class);
$this->assertSame($result1, $result2);
If you want to change default behavior you need to give to container's constructor array or another iterable
with following structure:
[
'config' => [
'Psr\Container\ContainerInterface::class' => [
'return_shared' => false
]
]
]
Also you can get a new object instead of the same as previously queried by using m0rtis\SimpleBox\Container::create(string $id)
method.
How to define services
You can use several different ways to define your services in container:
Callback function that receives the container as argument and returns initialized service (Pimple like way):
$container['serviceName'] = function (ContainerInterface $c) { return new AwesomeService($c->get('AwesomeServiceDependency')); };
Factory class name. Factory should be invokable (implement the magic method
__invoke
), has the word "factory" in its name and should not has any dependencies. The__invoke
method should accept aPsr\Container\ContainerInterface
as only argument:$container['serviceName'] = ServiceFactory::class; class ServiceFactory { public function __invoke(ContainerInterface $c) { return new AwesomeService($c->get('AwesomeServiceDependency')); } }
NOTE: The exception is the invokable classes (implements __invoke
magic method) without the word "factory" in its name. Such classes are callable too but SimpleBox container would not call them, just return as is. For example:
$service = $container->get(SomeInvokableClass::class); //$service instanceof SomeInvokableClass
$service = $container->get(ServiceFactory::class): //$service is the result returned by ServiceFactory::__invoke method
Autowiring
This chapter of README is under construction. But you can see tests as a simple example. And, of course, you can always ask me at the issues page or by e-mail.
Versioning
We use SemVer for versioning. For the versions available, see the tags on this repository.
Author
Anton Fomichev aka m0rtis - mail@m0rtis.ru
License
This project is licensed under the Apache 2.0 license - see the LICENSE file for details