Документация/Контейнер/Получение сервиса

Получение сервиса из контейнера

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


#Ссылка на контейнер в текущем классе

Классы, унаследованные от класса Hleb\Base\Container получают дополнительные возможности в виде методов и свойство $this->container для обращения к сервисам. Стандартные классы фреймворка — контроллеры, middlewares, команды, события, уже унаследованы от этого класса.

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

<?php
// File /app/Controllers/ExampleController.php

namespace App\Controllers;

use 
App\Bootstrap\Services\RequestIdInterface;
use 
Hleb\Base\Controller;

class 
ExampleController extends Controller
{
    public function 
index(): void
    
{
        
// variant 1
        
$requestIdService $this->container->get(RequestIdInterface::class);
        
// variant 2
        
$requestIdService $this->container->requestId();
    }
}

Ссылка на контейнер хранится в свойстве $this->config (ключ 'container' в массиве) объекта класса унаследованного от Hleb\Base\Container. При создании указанного объекта можно присвоить другое значение (например, c тестовым контейнером) в аргументе 'config'.
Иначе, если не указан конкретный контейнер в аргументе 'config' или отсутствует сам аргумент 'config' конструктора, то контейнер будет создан по умолчанию.

<?php

use App\Bootstrap\Services\RequestIdInterface;

class 
ExampleService extends \Hleb\Base\Container
{
    public 
RequestIdInterface $service;

    public function 
__construct(array $config = [])
    {
        
parent::__construct($config);

        
$this->service $this->container->get(RequestIdInterface::class);
    }
}

// Create an object with a framework container.
$requestIdService = (new ExampleService())->service;

// Create an object with a test container.
$config = ['container' => new TestContainer()];
$requestIdService = (new ExampleService($config))->service;

Исключения составляют классы Моделей, в них аналогичное получение сервиса будет таким:

<?php
// File /app/Models/DefaultModel.php

namespace App\Models;

use 
App\Bootstrap\Services\RequestIdInterface;
use 
Hleb\Base\Model;

class 
DefaultModel extends Model
{
    public static function 
getCollection(): array
    {
        
// variant 1
        
$requestIdService self::container()->get(RequestIdInterface::class);
        
// variant 2
        
$requestIdService self::container()->requestId();

        return [];
    }
}

#Класс Container

Доступ к контейнеру с сервисами предоставляет также класс Hleb\Static\Container, пример:

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

// variant 1
$container Container::getContainer();
$requestIdService $container->get(RequestIdInterface::class);

// variant 2
$requestIdService Container::get(RequestIdInterface::class);

#Стандартные сервисы

В папке /vendor/phphleb/framework/Static/ находятся классы-обёртки над стандартными сервисами фреймворка, которые можно использовать в коде аналогично классу Hleb\Static\Container, только для отдельных сервисов.
Эти сервисы можно получить и предыдущими перечисленными способами.

Из-за существования различных подходов в именовании интерфейсов, получение стандартных сервисов из контейнера может быть как по интерфейсу с окончанием Interface, так и без. Например, Hleb\Reference\RequestInterface аналогичен Hleb\Reference\Interface\Request.

Устройство контейнера Внедрение зависимостей

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