<?phpdeclare(strict_types=1);
useTemkaa\SimpleContainer\Container;
useTemkaa\SimpleContainer\Container\Builder;
// you need to provide SplFileInfo of config file to builder$configFile = newSplFileInfo('/path/to/config/file.yaml');
$container = (newBuilder())->add($configFile)->compile();
// or if you need multiple config files (for example for vendor package, why not?):$configFile1 = newSplFileInfo('/path/to/config/file_1.yaml');
$configFile2 = newSplFileInfo('/path/to/config/file_2.yaml');
$configFile3 = newSplFileInfo('/path/to/config/file_3.yaml');
$container = (newBuilder())
->add($configFile1)
->add($configFile2)
->add($configFile3)
->compile();
/** @var ClassName $object */$object = $container->get(ClassName::class);
// or if you have the class which has alias (from Alias attribute) then you can get its instance by alias$object = $container->get('class_alias');
// or if you have registered interface implementation in config you can get class which implements interface by calling$object = $container->get(InterfaceName::class);
Container config example:
services:
# list of global variable bindings which will be bound to variables with same name bind:
$variableName: env(GLOBAL_VARIABLE_VALUE)include:
# all class paths must be relative to config file to allow container find them
- '/../some/path/ClassName.php'
- '/../some/path/'exclude:
- '/../some/path/ClassName.php'
- '/../some/path/'# interface bindingApp\SomeInterface: App\SomeInterfaceImplementation# class info bindingApp\SomeClass:
bind:
$variableName: 'variable_value'$variableName2: 'env(ENV_VARIABLE)'$variableName3: 'env(ENV_VARIABLE_1)_env(ENV_VARIABLE_2)'$variableName4: !tagged tag_namedecorates:
id: App\SomeInterfacepriority: 1signature: decoratedsingleton: falsetags: [tag1, tag2, tag3]
<?phpdeclare(strict_types=1);
namespaceApp;
useTemkaa\SimpleContainer\Attribute\Decorates;
useTemkaa\SimpleContainer\Container\Builder;
interfaceSomeInterface
{
}
finalclassClassImplementingimplementsSomeInterface
{
}
#[Decorates(id: SomeInterface::class, priority: 0, signature: 'decorated')]
finalclassDecorator1implementsSomeInterface
{
publicfunction__construct(
private readonly SomeInterface$decorated,
) {
}
}
/** * the higher priority is, the closer is decorator to decorated service * in current example the result of decorators chain is: * Decorator1 decorates Decorator2, Decorator2 decorates ClassImplementing class. */
#[Decorates(id: SomeInterface::class, priority: 1)]
finalclassDecorator2implementsSomeInterface
{
publicfunction__construct(
private readonly SomeInterface$inner,
) {
}
}
finalclassCollector
{
publicfunction__construct(
private readonly SomeInterface$decoratedInterface,
) {
}
}
$container = (newBuilder())->add($configFile)->compile();
/* $object1 = new Collector(new Decorator1(new Decorator2(new ClassImplementing()))); */$object1 = $container->get(Collector::class);
/* $object2 = new Decorator1(new Decorator2(new ClassImplementing())); */$object2 = $container->get(SomeInterface::class);
Important notes:
if you have type hinted some class in class arguments of class, which is in include section
and which argument is neither in include and exclude sections, it will also be autowired.
Here are some improvements which will be implemented later:
refactoring
add decorator option to bind automatically decorated service if no other arguments exist (with different signature)
add ability to not bing interfaces if only one interface implementation exists
improve exception names and messages
allow binding variables with php/const notation (constant from classes or enums)
add option for binding objects through config and by attribute
As a developer i want to have an attribute which will make specific classes as not singletons to create a new instance of it object every time it is type-hinted somewhere