Giao diện
Service Providers
Giới thiệu (Introduction)
Service providers là nơi trung tâm của tất cả bootstrapping ứng dụng Laravel. Ứng dụng của bạn, cũng như tất cả core services của Laravel, đều được bootstrapped qua service providers.
"Bootstrapped" ở đây có nghĩa là gì? Nói chung, chúng ta muốn nói đăng ký (registering) mọi thứ, bao gồm đăng ký service container bindings, event listeners, middleware, và thậm chí routes. Service providers là nơi trung tâm để cấu hình ứng dụng.
Laravel nội bộ sử dụng hàng chục service providers để bootstrap các core services như mailer, queue, cache, v.v. Nhiều providers là "deferred" providers (trì hoãn), nghĩa là chúng không tải trên mọi request mà chỉ khi services chúng cung cấp thực sự cần thiết.
Tất cả service providers do người dùng định nghĩa được đăng ký trong file bootstrap/providers.php. Trong tài liệu sau, bạn sẽ học cách viết service providers riêng và đăng ký chúng.
GỢI Ý
Nếu bạn muốn tìm hiểu thêm cách Laravel xử lý requests và hoạt động nội bộ, xem tài liệu vòng đời request.
Viết Service Providers (Writing Service Providers)
Tất cả service providers kế thừa class Illuminate\Support\ServiceProvider. Hầu hết providers chứa method register và method boot. Trong method register, bạn chỉ nên bind vào service container. Không bao giờ cố đăng ký event listeners, routes, hay bất kỳ chức năng nào khác trong method register.
Artisan CLI có thể tạo provider mới qua lệnh make:provider. Laravel sẽ tự động đăng ký provider mới trong file bootstrap/providers.php:
bash
php artisan make:provider RiakServiceProviderMethod Register
Trong method register, chỉ nên bind vào service container. Không cố đăng ký event listeners, routes, hay chức năng khác — nếu không, bạn có thể vô tình sử dụng service từ provider chưa được tải.
Ví dụ service provider cơ bản:
php
<?php
namespace App\Providers;
use App\Services\Riak\Connection;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\ServiceProvider;
class RiakServiceProvider extends ServiceProvider
{
/**
* Đăng ký application services.
*/
public function register(): void
{
$this->app->singleton(Connection::class, function (Application $app) {
return new Connection(config('riak'));
});
}
}Provider này chỉ định nghĩa method register, dùng để đăng ký implementation của App\Services\Riak\Connection trong service container.
Properties bindings và singletons
Nếu service provider đăng ký nhiều simple bindings, bạn có thể dùng properties bindings và singletons thay vì đăng ký thủ công:
php
<?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
{
/**
* Tất cả container bindings cần đăng ký.
*
* @var array
*/
public $bindings = [
ServerProvider::class => DigitalOceanServerProvider::class,
];
/**
* Tất cả container singletons cần đăng ký.
*
* @var array
*/
public $singletons = [
DowntimeNotifier::class => PingdomDowntimeNotifier::class,
ServerProvider::class => ServerToolsProvider::class,
];
}Method Boot
Nếu bạn cần đăng ký view composer trong service provider, hãy thực hiện trong method boot. Method này được gọi sau khi tất cả service providers khác đã đăng ký, nghĩa là bạn có quyền truy cập tất cả services đã được framework đăng ký:
php
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap application services.
*/
public function boot(): void
{
View::composer('view', function () {
// ...
});
}
}Boot Method Dependency Injection
Bạn có thể type-hint dependencies cho method boot. Service container sẽ tự động inject dependencies cần thiết:
php
use Illuminate\Contracts\Routing\ResponseFactory;
/**
* Bootstrap application services.
*/
public function boot(ResponseFactory $response): void
{
$response->macro('serialized', function (mixed $value) {
// ...
});
}Đăng ký Providers (Registering Providers)
Tất cả service providers được đăng ký trong file cấu hình bootstrap/providers.php. File này trả về mảng chứa tên classes của service providers:
php
<?php
return [
App\Providers\AppServiceProvider::class,
];Khi bạn gọi lệnh Artisan make:provider, Laravel sẽ tự động thêm provider vào file bootstrap/providers.php. Tuy nhiên, nếu bạn tạo provider class thủ công, cần thêm provider vào mảng:
php
<?php
return [
App\Providers\AppServiceProvider::class,
App\Providers\ComposerServiceProvider::class,
];Deferred Providers (Providers trì hoãn)
Nếu provider chỉ đăng ký bindings trong service container, bạn có thể chọn defer (trì hoãn) việc đăng ký cho đến khi binding thực sự cần thiết. Trì hoãn tải provider cải thiện hiệu năng vì nó không tải từ filesystem trên mỗi request.
Laravel biên dịch và lưu trữ danh sách tất cả services được cung cấp bởi deferred providers. Chỉ khi bạn cố phân giải một trong số services này, Laravel mới tải service provider.
Để trì hoãn tải provider, implement interface \Illuminate\Contracts\Support\DeferrableProvider và định nghĩa method provides. Method provides trả về service container bindings được đăng ký bởi provider:
php
<?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
{
/**
* Đăng ký application services.
*/
public function register(): void
{
$this->app->singleton(Connection::class, function (Application $app) {
return new Connection($app['config']['riak']);
});
}
/**
* Lấy danh sách services được provider cung cấp.
*
* @return array<int, string>
*/
public function provides(): array
{
return [Connection::class];
}
}