Версия фреймворка:
5.4 4.2
Прогресс перевода
Перевод немного отстаёт от оригинала. Коммитов не переведено: 5

Сервис-провайдеры

Введение

Сервис-провайдеры лежат в основе первоначальной загрузки всех приложений на Laravel. И ваше приложение, и все базовые сервисы Laravel загружаются через сервис-провайдеры.

Но что мы понимаем под "первоначальной загрузкой"? В общих чертах, мы имеем ввиду регистрацию таких вещей, как биндингов в IoC-контейнер (фасадов и т.д.), слушателей событий, фильтров роутов и даже самих роутов. Сервис-провайдеры - центральное место для конфигурирования вашего приложения.

Если вы откроете файл config/app.php, поставляемый с Laravel, то увидите массив providers. В нём перечислены все классы сервис-провайдеров, которые загружаются для вашего приложения. Конечно, многие из них являются "отложенными" провайдерами, т.е. они не загружаются при каждом запросе, а только при необходимости.

В этом обзоре вы узнаете, как создавать свои собственные сервис-провайдеры и регистрировать их в своём приложении.

Использование сервис-провайдеров

Все сервис-провайдеры наследуют класс Illuminate\Support\ServiceProvider. В большинстве сервис-провайдеров есть методы register и boot. В методе register вы должны только привязывать свои классы в сервис-контейнер. Никогда не пытайтесь зарегистрировать слушателей событий, роуты и какие-либо другие возможности в методеregister.

С помощью Artisan CLI можно создать новый провайдер командой make:provider:

php artisan make:provider RiakServiceProvider

Метод Register

Как уже было сказано, внутри метода register, вы должны только привязывать свои классы в сервис-контейнер. Никогда не пытайтесь зарегистрировать слушателей событий, роуты и какие-либо другие возможности в методе register. Иначе вы можете случайно обратиться к сервису, предоставляемому сервис-провайдером, который ещё не был загружен.

Давайте взглянем на простой сервис-провайдер. Из любого метода вашего сервис-провайдера у вас всегда есть доступ к свойству $app, которое предоставляет доступ к сервис-контейнеру:

<?php

namespace App\Providers;

use Riak\Connection;
use Illuminate\Support\ServiceProvider;

class RiakServiceProvider extends ServiceProvider
{
    /**
     * Регистрация привязки в контейнере.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection(config('riak'));
        });
    }
}

Этот сервис-провайдер только определяет метод register и использует его, чтобы определить реализацию Riak\Connection в сервис-контейнере. Если вы не понимаете как работает сервис-контейнер, прочитайте его документацию.

Метод Boot

А что, если нам нужно зарегистрировать вью-композер в нашем сервис-провайдере? Это нужно делать в методе boot. Этот метод вызывают после того, как были зарегистрированы все другие сервис-провайдеры. И это значит, что у вас есть доступ ко всем другим сервисам, которые были зарегистрированы фреймворком:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{
    /**
     * Загрузка любых сервисов приложения..
     *
     * @return void
     */
    public function boot()
    {
        view()->composer('view', function () {
            //
        });
    }
}

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

Вы можете указать зависимости для метода boot вашего сервис-провайдера. Сервис-контейнер автоматически внедрит те зависимости, которые вы зададите:

use Illuminate\Contracts\Routing\ResponseFactory;

public function boot(ResponseFactory $response)
{
    $response->macro('caps', function ($value) {
        //
    });
}

Регистрация провайдеров

Все сервис-провайдеры регистрируются в конфиге config/app.php. В этом файле содержится массив providers, где можно добавить имена классов ваших сервис-провайдеров. По-умолчанию в нём указан набор базовых сервис-провайдеров Laravel. Эти провайдеры загружают базовые компоненты Laravel, такие как обработчик почты, очередь, кэш и другие.

Чтобы зарегистрировать свой сервис-провайдер, добавьте его в этот массив:

'providers' => [
    // Другие сервис-провайдеры

    App\Providers\ComposerServiceProvider::class,
],

Отложенные провайдеры

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

Laravel компилирует и хранит список всех сервисов, предоставляемых отложенными сервис-провайдерами, и их классов. Laravel загрузит нужный сервис-провайдер только когда в процессе работы приложению понадобится один из этих сервисов.

Для того, чтобы сделать сервис-провайдер отложенным, установите свойство defer равным true и определите метод provides. Метод provides должен вернуть привязки сервис-контейнера, зарегистрированные в вашем провайдере:

<?php

namespace App\Providers;

use Riak\Connection;
use Illuminate\Support\ServiceProvider;

class RiakServiceProvider extends ServiceProvider
{
    /**
     * Задаёт отложена ли загрузка провайдера.
     *
     * @var bool
     */
    protected $defer = true;

    /**
     * Регистрация сервис-провайдера.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection($app['config']['riak']);
        });
    }

    /**
     * Получить предоставляемые сервисы от провайдера.
     *
     * @return array
     */
    public function provides()
    {
        return [Connection::class];
    }

}