Сервіс-Провайдери

Вступ

Сервіс-провайдери є центральним місцем для всіх ініціалізаційних процесів 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];
}
}