<?php
class Container {
private array $factories = [];
public function addFactory(string $className, Factory $factory): void
{
$this->factories[$className] = $factory;
}
public function getInstance(string $className): object
{
return $this->factories[$className]->create();
}
}
abstract class Factory {
private Container $container;
private array $config = [];
public function __construct(Container $container, array $config = [])
{
$this->container = $container;
$instanceConfig = array_key_exists(static::getClass(), $config) ? $config[static::getClass()] : [];
$this->config = $instanceConfig;
}
abstract public static function getClass(): string;
public function create(): object
{
$class = static::getClass();
$parameters = [];
foreach($this->config['parameters'] as $name => $value) {
if (null === $value) {
$value = $this->container->getInstance($name);
}
$parameters[] = $value;
}
return new $class(...$parameters);
}
}
class FooFactory extends Factory {
public static function getClass(): string
{
return Foo::class;
}
}
class BarFactory extends Factory {
public static function getClass(): string
{
return Bar::class;
}
}
class Foo {
private Bar $bar;
private string $test;
public function __construct(Bar $bar, string $test)
{
$this->bar = $bar;
$this->test = $test;
}
}
class Bar {}
$config = [
Foo::class => [
'parameters' => [
Bar::class => null,
'test',
]
],
Bar::class => [
'parameters' => [],
],
];
$container = new Container;
$container->addFactory(FooFactory::getClass(), new FooFactory($container, $config));
$container->addFactory(BarFactory::getClass(), new BarFactory($container, $config));
$foo = $container->getInstance(Foo::class);
var_dump($container);
var_dump($foo);
- Output for 8.0.1 - 8.0.30, 8.1.0 - 8.1.33, 8.2.0 - 8.2.29, 8.3.0 - 8.3.25, 8.4.1 - 8.4.12
- object(Container)#1 (1) {
["factories":"Container":private]=>
array(2) {
["Foo"]=>
object(FooFactory)#2 (2) {
["container":"Factory":private]=>
*RECURSION*
["config":"Factory":private]=>
array(1) {
["parameters"]=>
array(2) {
["Bar"]=>
NULL
[0]=>
string(4) "test"
}
}
}
["Bar"]=>
object(BarFactory)#3 (2) {
["container":"Factory":private]=>
*RECURSION*
["config":"Factory":private]=>
array(1) {
["parameters"]=>
array(0) {
}
}
}
}
}
object(Foo)#5 (2) {
["bar":"Foo":private]=>
object(Bar)#4 (0) {
}
["test":"Foo":private]=>
string(4) "test"
}
preferences:
88.63 ms | 408 KiB | 5 Q