istok / container
DI / IoC container with `call(\Closure $fn): mixed` method
Requires
- php: ^8.1
- psr/container: ^2.0
Requires (Dev)
- phpunit/phpunit: ^9.5
- vimeo/psalm: ^4.22
Provides
README
composer require istok/container
- allow to call any
\Closure
withContainer::call(\Closure $fn): mixed
method - allow custom resolving by attributes (useful to fill DTO)
- allow param-name binding:
Container::argument(string $name, string $for, \Closure $resolver)
- provided with wrapper implementing PSR-11 (see
Istok\Container\Psr\StrictContainer
andIstok\Container\Psr\GreedyContainer
)
Registration methods
// Registration of cachable entry Container::singletone(string $id, string|\Closure $defitition); // This entry will not be cached Container::register(string $id, string|\Closure $defitition); // parameter $name of $for::__construct() will be resolved by given closure Container::argument(string $name, string $for, \Closure $resolver);
$definition
parameters will be resolved by Container
Retrieving
// take instance Container::make(string $id); /** * Call $fn with given arguments, using Container::make() for rest * @param array<string, mixed> $args */ Container::call(\Closure $fn, $args); /** * Psalm-friendly version, contains actual type check, T should be class or interface, result should be typeof T * @template T * @param class-string<T> $id * @return T */ Container::construct(string $id): object;
Identifier resolution order
- use direct registration
- use attributes, use if any suited
- try to construct
Closure arguments resolution
- apply explicitly provided arguments
- use
Container::get()
to resolve rest
Resolving by attributes
If target class has attribute that implements Istok\Container\Resolver
interface, instance of attribute will be constructed (by Container::get
, not ReflectionAttribute::newInstance()
), and then result of Resolver::resolve($targetName, ...$attributeArgs)
will be returned as result.
Service and Model resolving
According to Object Design Style Guide by Matthias Noback, there are two types of objects:
Two types of objects
In an application there are typically two types of objects:
- Service objects which either perform a task, or return a piece of information.
- Objects that hold some data, and optionally expose some behavior for manipulating or retrieving that data.
First type have a well-known name, Service
, and other one I called Model
(I have to called it someway).
While Services
depends on both other Services
and Models
, Models
depends only on other Models
and input
.
One of reasons why I want to create this container was the desire to be able to get well-typed DTOs filled from user input, or config, as arguments of my controllers.
To achieve this, I added Resolver
interface, which implementation can be used as attribute of Model
.
This allows to add contextual configuration for resolving this type of objects.
So, Container
itself is mostly for resolving Services
, and ModelResolver
used for resolving Models
, like request DTOs
.