什么是服务提供者
服务提供者是 Laravel 应用整体启动流程的核心。你自己的应用以及 Laravel 的所有核心服务,都是通过服务提供者进行启动的。
「启动(bootstrapping)」在这里意味着:注册服务容器的绑定、事件监听器、中间件、路由等各类内容。服务提供者是配置应用的中心位置。
Laravel 内部使用大量服务提供者来启动邮件、队列、缓存等核心服务。这些提供者中的许多是「延迟」提供者,只有真正需要其提供的服务时才会加载,而不是每次请求都加载。
用户自定义的服务提供者需要在 bootstrap/providers.php 文件中注册。
想更深入了解 Laravel 如何处理请求,请参阅请求生命周期文档。
编写服务提供者
所有服务提供者都继承自 Illuminate\Support\ServiceProvider。大多数服务提供者会同时包含 register 与 boot 方法。
要生成新的提供者,请使用 make:provider Artisan 命令。Laravel 会自动在 bootstrap/providers.php 中注册新的提供者。
php artisan make:provider RiakServiceProvider
register 方法
在 register 方法中,仅应向服务容器进行绑定注册。请勿在 register 中注册事件监听器、路由或其他功能——因为此时可能会错误地使用尚未加载的服务提供者所提供的服务。
<?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'));
});
}
}
服务提供者的方法内始终可以通过 $this->app 属性访问服务容器。
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,
];
/**
* 要注册的所有容器单例
*
* @var array
*/
public $singletons = [
DowntimeNotifier::class => PingdomDowntimeNotifier::class,
ServerProvider::class => ServerToolsProvider::class,
];
}
boot 方法
如需在服务提供者中注册视图 Composer,请写在 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 () {
// ...
});
}
}
请勿混淆 register 与 boot 方法的作用。register 仅用于注册绑定,boot 用于初始化服务和其他准备工作。
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,
];
在 Laravel 13 中,不再使用 config/app.php 的 providers 数组,而是通过 bootstrap/providers.php 注册服务提供者。make:provider 命令会自动添加。
运行 make:provider Artisan 命令时,Laravel 会自动在该文件里添加提供者。如果是手动创建的提供者类,请手动将其添加到数组中。
<?php
return [
App\Providers\AppServiceProvider::class,
App\Providers\ComposerServiceProvider::class,
];
创建自定义服务提供者
下面演示实际编写一个自定义服务提供者。
生成提供者
使用 Artisan 命令生成服务提供者。php artisan make:provider PaymentServiceProvider
在 register 方法中绑定
在生成的提供者的 register 方法中编写绑定。<?php
namespace App\Providers;
use App\Contracts\PaymentGateway;
use App\Services\StripePaymentGateway;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\ServiceProvider;
class PaymentServiceProvider extends ServiceProvider
{
/**
* 注册应用服务
*/
public function register(): void
{
$this->app->singleton(PaymentGateway::class, function (Application $app) {
return new StripePaymentGateway(
config('services.stripe.secret')
);
});
}
/**
* 启动应用服务
*/
public function boot(): void
{
// 如需启动时的处理,写在这里
}
}
注册到 bootstrap/providers.php
使用 make:provider 时会自动注册。若为手动创建,请添加:<?php
return [
App\Providers\AppServiceProvider::class,
App\Providers\PaymentServiceProvider::class,
];
延迟提供者(Deferred Providers)
如果提供者只用于注册服务容器绑定,那么可以推迟该提供者的注册,直到真正需要绑定时才加载。通过延迟这类提供者的加载,就不会在每次请求时都从文件系统加载,从而提升性能。
要创建延迟提供者,请实现 \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(config('riak'));
});
}
/**
* 获取该提供者所提供的服务
*
* @return array<int, string>
*/
public function provides(): array
{
return [Connection::class];
}
}
延迟提供者适合那些只在特定功能中使用(而非全局)的服务。避免加载不必要的服务,可以进一步优化性能。
下一步