Дополнительно/Специальные возможности/Контейнер и сервисы/Нестандартное использование контейнера

Нестандартное использование контейнера

Несмотря на то, что создание объекта в контейнере через new и c пустым конструктором является хорошей практикой, в конце концов вы можете вынести в отдельный метод специального класса создание всех необходимых зависимостей и зарегистрировать его выполнение в контейнере, несмотря на это есть способы разрешения зависимостей не прибегая к созданию отдельного класса-обёртки.

В случае возникновения необходимости переиспользовать сервис из контейнера для инициализации другого сервиса в контейнере обратимся к возможностям, которые даёт внедрение зависимостей. В классе App\Bootstrap\ContainerFactory эти методы доступны, как и в отдельном специальном классе для создания контейнера.

Например, необходимо проинициализировать конструктор сервиса в контейнере. Для этого в теле оператора match класса App\Bootstrap\ContainerFactory нужно добавить примерно такое соответствие:

// File /app/Bootstrap/ContainerFactory.php
use Hleb\Static\DI;
// ... //

ExampleService::class => new ExampleService(),

// variant 1
DemoService::class => new DemoService(DI::object(ExampleService::class)),

// variant 2
DemoService::class => DI::object(DemoService::class),

// ... //

Теперь в конструктор класса DemoService будет попадать текущий сервис ExampleService как он определен в контейнере. Все зависимости, не указанные явно, в используемом примере будут разрешены автоматически (вариант 2).

Важно следить за тем, чтобы зависимости не зациклились, это может быть в случае если при инициализации объекта в контейнере он повторно обращается в контейнер для инициализации этого же объекта.

Более сложный пример:

// File /app/Bootstrap/ContainerFactory.php
use Hleb\Static\DI;

// ... //

SenderServiceInterface::class => new MailTransportService(),

SiestaService::class => DI::method(DI::object(
    
SiestaService::class,
    [
        
'start' => (new DateTimeImmutable())->setTime(140),
        
'end' => (new DateTimeImmutable())->setTime(160),
    ]
), 
'setSender', ['transport' => DI::object(SenderServiceInterface::class)]),

// ... //

Подобным образом в контейнер фреймворка, несмотря на его кажущуюся простоту, можно добавлять различные взаимозависимые сервисы.

Страница создана: @fomiash
К началу страницы