Сервис-провайдеры
1. Введение
Сервис-провайдеры — это центральное место для инициализации всех приложений Laravel. Ваше собственное приложение, так же как и все основные сервисы Laravel, инициализируются через сервис-провайдеры.
Но что мы имеем в виду под "инициализацией"? В общем смысле, это означает регистрацию различных элементов, включая привязки в сервис-контейнере, слушатели событий, посредники и даже маршруты. Сервис-провайдеры — это центральное место для настройки вашего приложения.
Laravel использует десятки сервис-провайдеров для инициализации своих основных сервисов, таких как почтовая служба, очередь, кэш и другие. Многие из этих провайдеров являются "отложенными", то есть они не будут загружаться при каждом запросе, а только тогда, когда предоставляемые ими сервисы действительно понадобятся.
Все пользовательские сервис-провайдеры регистрируются в файле bootstrap/providers.php
. В следующей
документации вы узнаете, как писать собственные сервис-провайдеры и регистрировать их в вашем Laravel-приложении.
Если вы хотите узнать больше о том, как Laravel обрабатывает запросы и работает изнутри, ознакомьтесь с нашей документацией о жизненном цикле запроса в Laravel.
2. Создание сервис-провайдеров
Все сервис-провайдеры наследуются от класса Illuminate\Support\ServiceProvider
. Большинство
сервис-провайдеров содержат методы register
и boot
. Внутри метода register
вы должны только связывать объекты в сервис-контейнере.
Никогда не пытайтесь регистрировать слушатели событий, маршруты или любую другую функциональность внутри метода
register
.
Интерфейс командной строки Artisan может сгенерировать новый провайдер с помощью команды
make:provider
. Laravel автоматически зарегистрирует ваш новый провайдер в файле
bootstrap/providers.php
вашего приложения:
php artisan make:provider RiakServiceProvider
2.1. Метод Register
Как упоминалось ранее, в методе register
вы должны только связывать объекты в сервис-контейнере. Никогда не пытайтесь регистрировать слушатели событий,
маршруты или любую другую функциональность в методе register
. В противном случае вы можете случайно
использовать сервис, который предоставляется сервис-провайдером, который ещё не был загружен.
Рассмотрим базовый сервис-провайдер. В любом из методов вашего сервис-провайдера у вас всегда есть доступ к
свойству $app
, которое предоставляет доступ к сервис-контейнеру:
<?php namespace App\Providers; use App\Services\Riak\Connection;use Illuminate\Contracts\Foundation\Application;use Illuminate\Support\ServiceProvider; class RiakServiceProvider extends ServiceProvider{ /** * Register any application services. */ public function register(): void { $this->app->singleton(Connection::class, function (Application $app) { return new Connection(config('riak')); }); }}
Этот сервис-провайдер определяет только метод register
и использует его для определения реализации
App\Services\Riak\Connection
в сервис-контейнере. Если вы еще не знакомы с сервис-контейнером
Laravel, ознакомьтесь с его документацией.
2.1.1. Свойства bindings
и singletons
Если ваш сервис-провайдер регистрирует множество простых привязок, вы можете использовать свойства
bindings
и singletons
вместо ручной регистрации каждой привязки в контейнере. Когда
сервис-провайдер загружается фреймворком, он автоматически проверяет эти свойства и регистрирует их привязки:
<?php namespace App\Providers; use App\Contracts\DowntimeNotifier;use App\Contracts\ServerProvider;use App\Services\DigitalOceanServerProvider;use App\Services\PingdomDowntimeNotifier;use App\Services\ServerToolsProvider;use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider{ /** * All of the container bindings that should be registered. * * @var array */ public $bindings = [ ServerProvider::class => DigitalOceanServerProvider::class, ]; /** * All of the container singletons that should be registered. * * @var array */ public $singletons = [ DowntimeNotifier::class => PingdomDowntimeNotifier::class, ServerProvider::class => ServerToolsProvider::class, ];}
2.2. Метод Boot
Итак, что если нам нужно зарегистрировать view-composer (композер
представлений) в
нашем сервис-провайдере? Это следует делать в методе boot
. Этот метод вызывается после
регистрации всех остальных сервис-провайдеров, что означает, что у вас есть доступ ко всем другим
сервисам, зарегистрированным фреймворком:
<?php namespace App\Providers; use Illuminate\Support\Facades\View;use Illuminate\Support\ServiceProvider; class ComposerServiceProvider extends ServiceProvider{ /** * Bootstrap any application services. */ public function boot(): void { View::composer('view', function () { // ... }); }}
2.2.1. Внедрение зависимостей в метод Boot
Вы можете указать зависимости для метода boot
вашего сервис-провайдера. Сервис-контейнер автоматически внедрит все необходимые зависимости:
use Illuminate\Contracts\Routing\ResponseFactory; /** * Bootstrap any application services. */public function boot(ResponseFactory $response): void{ $response->macro('serialized', function (mixed $value) { // ... });}
3. Регистрация провайдеров
Все сервис-провайдеры регистрируются в конфигурационном файле bootstrap/providers.php
. Этот файл
возвращает массив, содержащий имена классов сервис-провайдеров вашего приложения:
<?php return [ App\Providers\AppServiceProvider::class,];
Когда вы вызываете Artisan-команду make:provider
, Laravel автоматически добавляет сгенерированный
провайдер в файл bootstrap/providers.php
. Однако, если вы создали класс провайдера вручную, вам
следует вручную добавить его в массив:
<?php return [ App\Providers\AppServiceProvider::class, App\Providers\ComposerServiceProvider::class, ];