Поставщики служб – это центральное место начальной загрузки всех приложений Laravel. Ваше собственное приложение, а также все основные службы Laravel загружаются через поставщиков.
Но, что мы подразумеваем под «начальной загрузкой»? В общем, мы имеем в виду регистрацию элементов, включая регистрацию связываний контейнера служб, слушателей событий, посредников и даже маршрутов. Поставщики служб являются центральным местом для конфигурирования приложения.
Если вы откроете файл config/app.php
, включенный в Laravel, вы увидите массив поставщиков. Это все классы поставщиков служб, которые будут загружены вашим приложением. По умолчанию в этом массиве перечислены основные поставщики служб Laravel. Эти поставщики загружают основные компоненты Laravel, такие как почтовая программа, очередь, кеш и другие. Многие из этих поставщиков являются «отложенными», что означает, что они не будут загружаться при каждом запросе, а только тогда, когда предоставляемые ими службы действительно необходимы.
В этой документации вы узнаете, как писать собственных поставщиков служб и регистрировать их в приложении Laravel.
Примечание
Если вы хотите узнать больше о том, как Laravel обрабатывает запросы и работает изнутри, ознакомьтесь с нашей документацией по жизненному циклу запроса Laravel.
Все поставщики служб расширяют класс Illuminate\Support\ServiceProvider
. Большинство поставщиков служб содержат метод register
и boot
. В рамках метода register
следует только связать сущности в контейнере служб. Никогда не следует пытаться зарегистрировать каких-либо слушателей событий, маршруты или любые другие функциональные возможности в методе register
.
Чтобы сгенерировать нового поставщика, используйте команду make:provider
Artisan:
php artisan make:provider RiakServiceProvider
Как упоминалось ранее, в рамках метода register
следует только связать сущности в контейнере служб. Никогда не следует пытаться зарегистрировать слушателей событий, маршруты или любую другую функциональность в методе register
. В противном случае вы можете случайно воспользоваться службой, которая еще не загружена.
Давайте взглянем на основного поставщика служб. В любом из методов поставщика служб у вас всегда есть доступ к свойству $app
, которое обеспечивает доступ к контейнеру служб:
<?php
namespace App\Providers;
use App\Services\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
и использует этот метод для определения реализации App\Services\Riak\Connection
в контейнере служб. Если вы еще не знакомы с контейнером служб Laravel, ознакомьтесь с его документацией.
Если ваш поставщик службы регистрирует много простых связываний, вы можете использовать свойства 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
{
/**
* Все связывания контейнера, которые должны быть зарегистрированы.
*
* @var array
*/
public $bindings = [
ServerProvider::class => DigitalOceanServerProvider::class,
];
/**
* Все синглтоны (одиночки) контейнера, которые должны быть зарегистрированы.
*
* @var array
*/
public $singletons = [
DowntimeNotifier::class => PingdomDowntimeNotifier::class,
ServerProvider::class => ServerToolsProvider::class,
];
}
Итак, что, если нам нужно зарегистрировать компоновщик шаблонов в нашем поставщике службы? Это должно быть сделано в рамках метода boot
. Этот метод вызывается после регистрации всех других поставщиков служб, что означает, что у вас есть доступ ко всем другим службам, которые были зарегистрированы фреймворком:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Загрузка любых служб приложения.
*
* @return void
*/
public function boot()
{
View::composer('view', function () {
//
});
}
}
Вы можете указывать тип зависимостей в методе boot
поставщика службы. Контейнер служб автоматически внедрит любые необходимые зависимости:
use Illuminate\Contracts\Routing\ResponseFactory;
/**
* Загрузка любых служб приложения.
*
* @param \Illuminate\Contracts\Routing\ResponseFactory $response
* @return void
*/
public function boot(ResponseFactory $response)
{
$response->macro('serialized', function ($value) {
//
});
}
Все поставщики служб регистрируются в файле конфигурации config/app.php
. Этот файл содержит массив providers
, в котором можно перечислить имена классов ваших поставщиков служб. По умолчанию в этом массиве перечислены основные поставщики служб Laravel. Эти поставщики загружают основные компоненты Laravel, такие как почтовая программа, очереди, кеш и другие.
Чтобы зарегистрировать поставщика, добавьте его в массив:
'providers' => [
// Другие поставщики служб
App\Providers\ComposerServiceProvider::class,
],
Если ваш поставщик регистрирует только связывания в контейнере служб, вы можете отложить его регистрацию до тех пор, пока одно из зарегистрированных связываний не понадобится. Отсрочка загрузки такого поставщика повысит производительность вашего приложения, так как он не загружается из файловой системы при каждом запросе.
Laravel составляет и сохраняет список всех служб, предоставляемых отложенными поставщиками служб, а также имя класса поставщика службы. Laravel загрузит поставщика службы только при необходимости в одной из этих служб.
Чтобы отложить загрузку поставщика, реализуйте интерфейс \Illuminate\Contracts\Support\DeferrableProvider
, описав метод provides
. Метод provides
должен вернуть связывания контейнера службы, регистрируемые поставщиком:
<?php
namespace App\Providers;
use App\Services\Riak\Connection;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
class RiakServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Регистрация любых служб приложения.
*
* @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];
}
}