Piszemy kontener, za pomocą którego będziemy wstrzykiwać zależności. Kontynuacja lekcji o refleksji i grafie zależności. Do dzieła.

Na początek klasa z konstruktorem, którego parametrami są typy proste (nie podlega rekurencji dla obiektów):

class Person {
    
    public function __construct(public string $name, public int $age)
    {
        
    }
}

Teraz inna, nieznana klasa, z konstruktorem bez parametrów:

class UnknownClass {
    public string $name;
    public int $age;

    public function __construct()
    {
        $this->name = 'Prototype';
        $this->age = 30;
    }
}

Teraz kontener z rejesterm i możliwością zapisywania doń:

class Container {
    private array $registry = [];

    public function set(string $name, Closure $value): void
    {
        $this->registry[$name] = $value;
    }
}

Tak to zapisywanie będzie wyglądać w praktyce:

$container = new Container;
$container->set(Person::class, function(){
    return new Person("Prototype Name", 30);
});

Czyli klasa, która potrzebuje jakichś argumentów prostych będzie musiała być w rejestrze razem z tymi argumentami w postaci closure.

Teraz metoda get:

class Container {
    private array $registry = [];

    public function set(string $name, Closure $value): void
    {
        $this->registry[$name] = $value;
    }

    public function get(string $className) : object {
        if (array_key_exists($className, $this->registry)) {
            return $this->registry[$className]();
        }
        return new $className;
    }

}

A teraz przykład działania:

$container = new Container;
$container->set(Person::class, function(){
    return new Person("Prototype Name", 30);
});

$person = $container->get(Person::class);
print_r($person);
//Person Object ( [name] => Prototype Name [age] => 30 )

$unknown = $container->get(UnknownClass::class);
print_r($unknown);
//UnknownClass Object ( [name] => Prototype [age] => 30 )

Wszystko można połączyć z grafem zależności znanym z lekcji poprzedniej, ale tym zajmiemy się w następnej lekcji.