Service Locator
Service Locator — это шаблон проектирования для управления сервисами приложения. Вместо создания сервисов напрямую, используется специальный объект — Service Locator. Он отвечает за создание и поиск сервисов, что упрощает их использование и замену.
Класс \Bitrix\Main\DI\ServiceLocator реализует интерфейс PSR-11. Доступен с версии main 20.5.400.
Пример использования:
$serviceLocator = \Bitrix\Main\DI\ServiceLocator::getInstance();
if ($serviceLocator->has('someService'))
{
$someService = $serviceLocator->get('someService');
}
Режим Autowire
По умолчанию Service Locator работает в режиме Autowire — автоматически разрешает все зависимости у сервисов.
Также контейнер может автоматически создавать объекты указанных классов, даже если их нет внутри контейнера.
$serviceInstance = \Bitrix\Main\DI\ServiceLocator::getInstance()->get(\VendorName\SomeModule\Services\SomeService::class);
Конфигурация сервиса
Конфигурация определяет способ создания объекта. Возможны три варианта:
-
Указать класс сервиса. Service Locator создаст сервис вызвав
new $className.'someModule.someServiceName' => [ 'className' => \VendorName\SomeModule\Services\SomeService::class, ] -
Указать класс сервиса и параметры конструктора. Service Locator создаст сервис вызвав
new $className('foo', 'bar').'someModule.someServiceName' => [ 'className' => \VendorName\SomeModule\Services\SomeService::class, 'constructorParams' => ['foo', 'bar'], ] -
Указать замыкание-конструктор. Он создаст и вернет объект сервиса.
'someModule.someAnotherServiceName' => [ 'constructor' => static function () { return new \VendorName\SomeModule\Services\SecondService('foo', 'bar'); }, ]
В качестве ключа, который реализует сервис, можно использовать строку, имя класса или интерфейса.
'someModule.someServiceName' => [
'className' => \VendorName\SomeModule\Services\SomeService::class,
],
\VendorName\SomeModule\Contracts\SomeInterface::class => [
'className' => \VendorName\SomeModule\Services\SomeService::class,
],
Регистрация сервиса
Чтобы обратиться к сервису, его нужно зарегистрировать одним из способов.
-
Через файл настроек bitrix/.settings.php
В Bitrix Framework файлы
.settings.phpиспользуются для хранения конфигураций. Они находятся в корне проекта и содержат секции для различных настроек, таких как базы данных, кеширование и сервисы.Сервисы регистрируются в секции services.
// /bitrix/.settings.php return [ 'services' => [ 'value' => [ 'someServiceName' => [ 'className' => \VendorName\Services\SomeService::class, ], \VendorName\SomeModule\Contracts\SecondInterface::class => [ 'className' => \VendorName\Services\SecondService::class, 'constructorParams' => ['foo', 'bar'], ], ], 'readonly' => true, ], ];После инициализации ядра сервисы становятся доступны.
$serviceLocator = \Bitrix\Main\DI\ServiceLocator::getInstance(); $someGoodServiceName = $serviceLocator->get('someGoodServiceName'); $someServiceName = $serviceLocator->get('someServiceName'); -
Через файл настроек модуля {moduleName}/.settings.php
Файл
.settings.phpв корне модуля описывает сервисы модуля. Это позволяет модулям иметь свои собственные настройки и сервисы, которые не зависят от глобальных настроек.// someModule/.settings.php return [ 'services' => [ 'value' => [ 'someModule.someServiceName' => [ 'className' => \VendorName\SomeModule\Services\SomeService::class, ], 'someModule.someAnotherServiceName' => [ 'constructor' => static function () { return new \VendorName\SomeModule\Services\SecondService('foo', 'bar'); }, ], \VendorName\SomeModule\Contracts\SecondInterface::class => [ 'className' => \VendorName\SomeModule\Services\SecondService::class, 'constructorParams' => static function () { return ['foo', 'bar']; }, ], ], 'readonly' => true, ], ];Сервисы регистрируются после подключения модуля. Используйте префикс имени модуля для уникальности, например:
disk.urlManager,crm.urlManager. -
Через API
Регистрация через API осуществляется методами класса \Bitrix\Main\DI\ServiceLocator.
-
getInstance()— получить экземпляр локатора. -
addInstance(string $code, $service)— зарегистрировать экземпляр сервиса. -
addInstanceLazy(string $code, $configuration)— выполнить ленивую регистрацию с конфигурацией, при которой система создаст сервис только при обращении к нему. -
has(string $code)— проверить наличие сервиса. -
get(string $code)— получить сервис. Метод создает сервис при первом обращении. Если сервиса нет, выбрасывается исключение \Psr\Container\NotFoundExceptionInterface.
Подробное описание методов — в справочнике API.
-