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

Добавление сервиса в контейнер

В разделе с описанием Контейнера для фреймворка HLEB2 данной документации уже есть простой пример с добавлением демонстрационного сервиса. Далее рассмотрим пример с добавлением реальной библиотеки для мьютексов как Сервиса.

Библиотека github.com/phphleb/conductor содержит механизм мьютексов, если вы собираетесь использовать эту библиотеку, то её нужно сначала установить.

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

Внешние библиотеки лучше подключать к проекту используя паттерн Адаптер, класс которого и будет ключом сервиса в контейнере.

<?php
// File /app/Bootstrap/Services/MutexService.php

namespace App\Bootstrap\Services;

use 
Phphleb\Conductor\Src\Scheme\MutexInterface;

class 
MutexService
{
    public function 
__construct(private MutexInterface $mutex) { }

    public function 
acquire(string $name, ?int $sec null): bool
    
{
        return 
$this->mutex->acquire($name$sec);
    }

    public function 
release(string $name): bool
    
{
        return 
$this->mutex->release($name);
    }

    public function 
unlock(string $name): bool
    
{
        return 
$this->mutex->unlock($name);
    }
}

Этот класс обёртки для сервиса создан в папке /app/Bootstrap/Services/. Несмотря на то, что это удобная директория для примеров, структурно папка с Сервисами должна находиться рядом с логикой проекта.

Теперь добавим библиотеку в контейнер по созданному классу:

<?php
// File /app/Bootstrap/ContainerFactory.php

namespace App\Bootstrap;

use 
App\Bootstrap\Services\MutexService;
use 
Hleb\Constructor\Containers\BaseContainerFactory;
use 
Phphleb\Conductor\FileMutex;
use 
Phphleb\Conductor\Src\MutexDirector;

final class 
ContainerFactory extends BaseContainerFactory
{
    public static function 
getSingleton(string $id): mixed
    
{
        
self::has($id) or self::$singletons[$id] = match ($id) {
            
// New service as singleton.
            
MutexService::class => new MutexService(new FileMutex()),

            
// ... //
            
default => null
        
};
        return 
self::$singletons[$id];
    }

    public static function 
rollback(): void
    
{
        
// Rollback for an asynchronous request.
        
MutexDirector::rollback();

        
// ... //
    
}
}

На примере видно, что в метод rollback() добавлен сброс состояния для подключенной библиотеки мьютексов, которая поддерживает асинхронность.

После добавления новый сервис доступен из контейнера по этому классу как singleton.

use App\Bootstrap\Services\MutexService;
use 
Hleb\Static\Container;

$mutex Container::get(MutexService::class);

Способ использования добавленного сервиса в контроллерах, командах и событиях (во всех классах, унаследованных от Hleb\Base\Container):

use App\Bootstrap\Services\MutexService;

$mutex $this->container->get(MutexService::class);

Упростить приведённый вызов сервиса можно при добавлении нового одноимённого метода mutex() в класс App\Bootstrap\BaseContainer и его интерфейс:

use App\Bootstrap\Services\MutexService;

#[\Override]
final public function 
mutex(): MutexService
{
    return 
$this->get(MutexService::class);
}

Теперь вызов будет выглядеть так:

$mutex $this->container->mutex();
Страница создана: @fomiash
К началу страницы