Service Locator

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

В Yii локатор службы является просто экземпляром класса yii\di\ServiceLocator или дочернего класса.

Наиболее часто используемый локатор сервиса в Yii - это объект приложения, к которому можно получить доступ через приложение \Yii::$app, которые он предоставляет, называются компонентами приложения, такими как компоненты request, response и urlManager. Вы можете настроить эти компоненты или даже заменить их на свои собственные реализации, легко через функциональность, предоставляемую локатором сервисов. Помимо объекта приложения, каждый объект модуля также является локатором сервиса.

Чтобы использовать локатор сервиса, первым шагом является регистрация компонентов с ним. Компонент можно зарегистрировать через yii\di\ServiceLocator::set(). Следующий код показывает различные способы регистрации компонентов:

use yii\di\ServiceLocator;
use yii\caching\FileCache;

$locator = new ServiceLocator;

// register "cache" using a class name that can be used to create a component
$locator->set('cache', 'yii\caching\ApcCache');

// register "db" using a configuration array that can be used to create a component
$locator->set('db', [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=demo',
    'username' => 'root',
    'password' => '',
]);

// register "search" using an anonymous function that builds a component
$locator->set('search', function () {
    return new app\components\SolrService;
});

// register "pageCache" using a component
$locator->set('pageCache', new FileCache);

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

$cache = $locator->get('cache');
// or alternatively
$cache = $locator->cache;

Как показано выше, yii\di\ServiceLocator позволяет вам получить доступ к компоненту подобно свойству, используя идентификатор компонента. Когда вы впервые обращаетесь к компоненту, yii\di\ServiceLocator будет использовать информацию о регистрации компонента, чтобы создать новый экземпляр компонента и вернуть его. Позже, если компонент будет снова доступен, локатор сервиса вернет тот же экземпляр.

Вы можете использовать yii\di\ServiceLocator::has(), чтобы проверить, зарегистрирован ли идентификатор компонента. Если вы вызовете yii\di\ServiceLocator::get() с недопустимым идентификатором, будет возбуждено исключение.

Поскольку локаторы служб часто создаются с конфигурациями, предоставляется доступное для записи свойство с именем components. Это позволяет вам настроить и зарегистрировать сразу несколько компонентов. Следующий код показывает массив конфигурации, который можно использовать для настройки локатора службы (например, приложения) с компонентами db, cache и search:

return [
    // ...
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=demo',
            'username' => 'root',
            'password' => '',
        ],
        'cache' => 'yii\caching\ApcCache',
        'search' => function () {
            $solr = new app\components\SolrService('127.0.0.1');
            // ... other initializations ...
            return $solr;
        },
    ],
];

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

class SolrServiceBuilder
{
    public static function build($ip)
    {
        return function () use ($ip) {
            $solr = new app\components\SolrService($ip);
            // ... other initializations ...
            return $solr;
        };
    }
}

return [
    // ...
    'components' => [
        // ...
        'search' => SolrServiceBuilder::build('127.0.0.1'),
    ],
];

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