Введение
Поставщики услуг, или сервис-провайдеры (service providers), лежат в основе «первоначальной загрузки» всего Laravel. И ваше приложение, и все базовые сервисы Laravel загружаются через сервис-провайдеры.
Но что мы понимаем под «первоначальной загрузкой»? В основном это регистрация таких вещей как привязки сервис-контейнера, слушатели событий, посредники и даже маршруты. Сервис-провайдеры — центральное место для настройки вашего приложения.
Если вы откроете файл config/app.php, поставляемый с Laravel, то вы увидите массив providers. В нём перечислены все классы сервис-провайдеров, которые загружаются для вашего приложения. Конечно, многие из них являются «отложенными» (deferred), они не загружаются при каждом запросе, а только при необходимости.
В этом обзоре вы узнаете, как создавать свои собственные сервис-провайдеры и регистрировать их в своём приложении.
Создание сервис-провайдеров
Все сервис-провайдеры наследуют класс Illuminate\Support\ServiceProvider. В большинстве сервис-провайдеров есть методы PHPregister()
и PHPboot()
. В методе PHPregister()
вы должны только привязывать свои классы в сервис-контейнер. Никогда не пытайтесь зарегистрировать в этом методе слушателей событий, маршруты и какие-либо другие возможности.
С помощью Artisan CLI можно создать новый провайдер командой shmake:provider
:
shphp artisan make:provider RiakServiceProvider
Метод register()
Как уже было сказано, внутри метода PHPregister()
вы должны только привязывать свои классы в сервис-контейнер. Никогда не пытайтесь зарегистрировать в этом методе слушателей событий, маршруты и какие-либо другие возможности. Иначе может получиться, что вы обратитесь к сервису, предоставляемому сервис-провайдером, который ещё не был загружен.
Давайте взглянем на простой сервис-провайдер. Из любого метода вашего сервис-провайдера у вас всегда есть доступ к свойству $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) {
//для версии 5.1 и ранее:
//$this->app->singleton('Riak\Contracts\Connection', function ($app) {
return new Connection(config('riak'));
});
}
}
Этот сервис-провайдер только определяет метод PHPregister()
и использует его, чтобы определить реализацию Riak\Connection (для версии 5.1 и ранее — Riak\Contracts\Connection) в сервис-контейнере. Если вы не поняли, как работает сервис-контейнер, прочитайте его документацию.
добавлено в 5.0 ()
Метод boot()
А что, если нам нужно зарегистрировать построитель представления в нашем сервис-провайдере? Это нужно делать в методе PHPboot
. Этот метод вызывают после того, как все другие сервис-провайдеры были зарегистрированы. Это значит, что у вас есть доступ ко всем другим сервисам, которые были зарегистрированы фреймворком.
добавлено в 5.3 ()
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Загрузка любых сервисов приложения.
*
* @return void
*/
public function boot()
{
view()->composer('view', function () {
//
});
}
}
добавлено в 5.2 ()
<?php
namespace App\Providers;
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
// Свойства других сервис-провайдеров...
/**
* Регистрация всех остальных событий для вашего приложения.
*
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @return void
*/
public function boot(DispatcherContract $events)
{
parent::boot($events);
view()->composer('view', function () {
//
});
}
}
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* Загрузка сервисов после регистрации.
*
* @return void
*/
public function boot()
{
view()->composer('view', function () {
//
});
}
/**
* Привязка к контейнеру.
*
* @return void
*/
public function register()
{
//
}
}
Внедрение зависимостей метода PHPboot()
Вы можете указать зависимости для метода PHPboot()
вашего сервис-провайдера. Сервис-контейнер автоматически внедрит те зависимости, которые вы зададите:
use Illuminate\Contracts\Routing\ResponseFactory;
public function boot(ResponseFactory $response)
{
$response->macro('caps', function ($value) {
//
});
}
Регистрация провайдеров
Все сервис-провайдеры регистрируются в файле PHPconfig/app.php
путем добавления имён их классов в массив providers. Изначально в нём указан набор базовых сервис-провайдеров Laravel. Эти провайдеры загружают базовые компоненты Laravel, такие как обработчик почты, очередь, кэш и другие.
Чтобы зарегистрировать свой сервис-провайдер, просто добавьте его в этот массив:
'providers' => [
// Другие сервис-провайдеры
App\Providers\ComposerServiceProvider::class,
],
Отложенные провайдеры
Если ваш провайдер только регистрирует привязки в сервис-контейнере, то вы можете отложить регистрацию до момента, когда одна из этих привязок будет запрошена из сервис-контейнера. Это позволит не дёргать файловую систему при каждом запросе, что увеличит производительность вашего приложения.
Laravel собирает и хранит список всех сервисов, предоставляемых отложенными сервис-провайдерами, и их классов. Когда в процессе работы приложению понадобится один из этих сервисов, Laravel загрузит нужный сервис-провайдер.
Для того, чтобы сделать сервис-провайдер отложенным, установите свойство defer в true и определите метод PHPprovides()
. Метод PHPprovides()
должен вернуть привязки сервис-контейнера, зарегистрированные в вашем провайдере:
<?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) {
//Для версии 5.1 и ранее:
//$this->app->singleton('Riak\Contracts\Connection', function ($app) {
return new Connection($app['config']['riak']);
});
}
/**
* Получить сервисы от провайдера.
*
* @return array
*/
public function provides()
{
return [Connection::class];
//Для версии 5.1 и ранее:
//return ['Riak\Contracts\Connection'];
}
}
Комментарии (3)
Добрый день. У меня на хостинге с собственным сервис-провайдером возникает ошибка «Class does not exist». На локальном компьютере сервис-провайдер работает исправно. В чем может быть проблема?
composer dumpautoload
Проверьте имена папок и файлов. Локально (win, mac) большая/маленькая первая буква роли не играет, а на хостинге (linux) играет. И composer просто не находит нужный файл.