Yet another dependency injection container.
$ composer require jnjxp/container
Define how to create entries based on string identifier.
// Given
use Jnjxp\Container\Container;
class Foo {
public function __construct(public int $dependency) { }
}
class Bar extends Foo { }
class BarFactory {
public function __invoke() { return new Bar(1); }
}
// Configure Container
$factories = [
Foo::class => fn() => new Foo(1), // callable
Bar::class => BarFactory::class, // string identifier
];
$container = new Container(factories: $factories);
// Use Container
$foo = $container->get(Foo::class);
$bar = $container->get(Bar::class);
print_r($foo);
print_r($bar);
// Foo Object
// (
// [dependency] => 1
// )
// Bar Object
// (
// [dependency] => 1
// )
Container
is passed to factories.
// Given
use Jnjxp\Container\Container;
use Psr\Container\ContainerInterface as CI;
class Foo {
public function __construct(public Bar $bar) { }
}
class Bar {}
// Configure Container
$factories = [
Foo::class => fn(CI $container) => new Foo($container->get(Bar::class)),
Bar::class => fn() => new Bar(),
];
$container = new Container(factories: $factories);
// Use Container
$foo = $container->get(Foo::class);
print_r($foo);
// Foo Object
// (
// [bar] => Bar Object
// (
// )
//
// )
Add additional identifiers to entries.
// Given
use Jnjxp\Container\Container;
interface FooInterface {}
class Foo implements FooInterface {}
// Configure Container
$factories = [ Foo::class => fn() => new Foo() ];
$aliases = [
FooInterface::class => Foo::class
];
$container = new Container(
factories: $factories,
aliases: $aliases,
);
// Use Container
$foo = $container->get(FooInterface::class);
print_r($foo);
// Foo Object
// (
// )
Container won't look for factories or extensions.
// Given
use Jnjxp\Container\Container;
// Configure Container
$instances = [ 'FOO' => 'foo' ];
$container = new Container(
instances: $instances,
);
// Use Container
$foo = $container->get('FOO');
echo "$foo\n";
//foo
- Should be an
array
of callables or identifiers that resolve to them. - 1st parameter is the
Container
, 2nd is the existing Instance. (should be swapped) - The entry will be replaced by what is returned from the extension.
// Given
use Jnjxp\Container\Container;
use Psr\Container\ContainerInterface as CI;
class Foo {}
class FooDecorator
{
public function __construct(public Foo $foo) { }
}
class Bar { public $bar ; }
// Configure Container
$extensions = [
Foo::class => [ fn(CI $container, Foo $foo) => new FooDecorator($foo) ],
Bar::class => [ function(CI $container, Bar $bar) { $bar->bar = 1 ; return $bar; } ],
];
$container = new Container(
extensions: $extensions,
);
// Use Container
$foo = $container->get(Foo::class);
$bar = $container->get(Bar::class);
print_r($foo);
print_r($bar);
// FooDecorator Object
// (
// [foo] => Foo Object
// (
// )
//
// )
// Bar Object
// (
// [bar] => 1
// )
Enable auto-wiring by providing an AutowireInterface
// Given
use Jnjxp\Container\Container;
use Jnjxp\Container\Autowire\Autowire;
class Foo {
public function __construct(public Bar $bar) { }
}
class Bar { }
// Configure Container
$autowire = new Autowire();
$container = new Container(
autowire: $autowire,
);
// Use Container
$foo = $container->get(Foo::class);
print_r($foo);
// Foo Object
// (
// [bar] => Bar Object
// (
// )
//
// )
use Psr\Container\ContainerInterface;
interface AutowireInterface
{
public function create(string $className, ?ContainerInterface $container = null): object;
}
User ContainerBuilder
to build a Container
.
use Jnjxp\Container\ContainerBuilder;
$builder = new Builder();
// set factories
$builder->factory($name, $factory);
$builder->factories($factories);
// set aliases
$builder->alias($alias, $identifier);
$builder->aliases($aliases);
//set instances
$builder->instance($name, $instance);
$builder->instances($instances);
// set extensions
$builder->extension($name, $extension);
$builder->extensions($extensions);
// enable auto-wiring
$builder->autowire(true);
$builder->autowire($autowireImplementation);
// disable auto-wiring
$builder->autowire(false);
// Bulid the Container
$container = $builder->build();
Service Providers can define factories and extensions in the ContainerBuilder
.
See container-interop/service-provider.
namespace Interop\Container;
interface ServiceProviderInterface
{
public function getFactories();
public function getExtensions();
}
// Given
use Jnjxp\Container\ContainerBuilder;
use Jnjxp\Container\ServiceProvider\BaseServiceProvider;
class Foo {
public function __construct(public int $dependency) { }
}
class ServiceProvider extends BaseServiceProvider
{
public function getFactories(): array
{
return [ Foo::class => fn() => new Foo(1) ];
}
}
$builder = new ContainerBuilder();
$builder->provider(ServiceProvider::class);
$container = $builder->build();
$foo = $container->get(Foo::class);
print_r($foo);
// Foo Object
// (
// [dependency] => 1
// )