Сервіс-Провайдери
Вступ
Сервіс-провайдери є центральним місцем для всіх ініціалізаційних процесів Laravel-застосунку. Ваш власний застосунок, а також усі основні сервіси Laravel, ініціалізуються через сервіс-провайдери.
Але що ми маємо на увазі під "завантаженням"? Загалом, ми маємо на увазі реєстрацію речей, включаючи реєстрацію прив'язок сервіс-контейнера, слухачів подій, проміжного програмного забезпечення і навіть маршрутів. Сервіс-провайдери є центральним місцем для налаштування вашого застосунку.
Laravel використовує десятки сервіс-провайдерів внутрішньо для завантаження своїх основних сервісів, таких як поштовий сервіс, черга, кеш та інші. Багато з цих провайдерів є "відкладеними" провайдерами, що означає, що вони не будуть завантажені при кожному запиті, а лише тоді, коли сервіси, які вони надають, дійсно потрібні.
Усі користувацькі сервіс-провайдери реєструються у файлі bootstrap/providers.php. У наступній документації ви дізнаєтеся, як написати власні сервіс-провайдери та зареєструвати їх у вашому Laravel застосунку.
Якщо ви хочете дізнатися більше про те, як Laravel обробляє запити та працює внутрішньо, перегляньте нашу документацію про життєвий цикл запиту Laravel.
Написання Сервіс-провайдерів
Усі Сервіс-провайдери розширюють клас Illuminate\Support\ServiceProvider. Більшість Сервіс-провайдерів містять методи register та boot. У методі register ви повинні лише зв'язувати речі в сервіс-контейнер. Ви ніколи не повинні намагатися реєструвати будь-які слухачі подій, маршрути або будь-які інші частини функціональності в методі register.
Artisan CLI може згенерувати нового провайдера за допомогою команди make:provider. Laravel автоматично зареєструє ваш новий провайдер у файлі bootstrap/providers.php вашого застосунку:
php artisan make:provider RiakServiceProvider
Метод 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 { /** * Зареєструйте будь-які сервіси застосунку. */ public function register(): void { $this->app->singleton(Connection::class, function (Application $app) { return new Connection(config('riak')); }); } }
Цей Сервіс-провайдер визначає лише метод register і використовує цей метод для визначення реалізації App\Services\Riak\Connection у Сервіс-контейнері. Якщо ви ще не знайомі з Сервіс-контейнером Laravel, перегляньте його документацію.
Властивості 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 { /** * Усі прив'язки контейнера, які слід зареєструвати. * * @var array */ public $bindings = [ ServerProvider::class => DigitalOceanServerProvider::class, ]; /** * Усі singleton контейнера, які слід зареєструвати. * * @var array */ public $singletons = [ DowntimeNotifier::class => PingdomDowntimeNotifier::class, ServerProvider::class => ServerToolsProvider::class, ]; }
Метод Boot
Отже, що робити, якщо нам потрібно зареєструвати композитор представлення у нашому сервіс-провайдері? Це слід робити в методі boot. Цей метод викликається після того, як всі інші сервіс-провайдери були зареєстровані, тобто ви маєте доступ до всіх інших сервісів, які були зареєстровані фреймворком:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Ініціалізуйте будь-які сервіси застосунку.
*/
public function boot(): void
{
View::composer('view', function () {
// ...
});
}
}
Метод Boot Впровадження Залежностей
Ви можете вказати залежності для методу boot вашого сервіс-провайдера. Сервіс-контейнер автоматично впровадить будь-які залежності, які вам потрібні:
use Illuminate\Contracts\Routing\ResponseFactory; /** * Ініціалізуйте будь-які сервіси застосунку. */ public function boot(ResponseFactory $response): void { $response->macro('serialized', function (mixed $value) { // ... }); }
Реєстрація Провайдерів
Усі сервіс-провайдери реєструються у конфігураційному файлі 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,
];
Відкладені Провайдери
Якщо ваш провайдер лише реєструє зв'язування в сервіс-контейнері, ви можете відкласти його реєстрацію до моменту, коли одне з зареєстрованих зв'язувань дійсно знадобиться. Відкладання завантаження такого провайдера покращить продуктивність вашого застосунку, оскільки він не завантажується з файлової системи при кожному запиті.
Laravel компілює та зберігає список усіх сервісів, які постачаються відкладеними Сервіс-провайдерами, разом з назвою класу його Сервіс-провайдера. Потім, лише коли ви намагаєтеся вирішити один з цих сервісів, Laravel завантажує Сервіс-провайдер.
Щоб відкласти завантаження провайдера, реалізуйте інтерфейс \Illuminate\Contracts\Support\DeferrableProvider і визначте метод provides. Метод provides повинен повертати прив'язки сервіс-контейнера, зареєстровані провайдером:
<?php namespace App\Providers; use App\Services\Riak\Connection; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Support\DeferrableProvider; use Illuminate\Support\ServiceProvider; class RiakServiceProvider extends ServiceProvider implements DeferrableProvider { /** * Зареєструйте будь-які сервіси застосунку. */ public function register(): void { $this->app->singleton(Connection::class, function (Application $app) { return new Connection($app['config']['riak']); }); } /** * Отримати сервіси, які надає провайдер. * * @return array<int, string> */ public function provides(): array { return [Connection::class]; } }
