> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# 服务提供者

> 介绍如何使用 Laravel 服务提供者注册与启动应用中的服务。

## 什么是服务提供者

服务提供者是 Laravel 应用整体启动流程的核心。你自己的应用以及 Laravel 的所有核心服务，都是通过服务提供者进行启动的。

「启动（bootstrapping）」在这里意味着：**注册**服务容器的绑定、事件监听器、中间件、路由等各类内容。服务提供者是配置应用的中心位置。

```mermaid theme={null}
flowchart TD
    A["应用启动"] --> B["读取 bootstrap/providers.php"]
    B --> C["实例化所有提供者"]
    C --> D["调用所有提供者的 register()<br>仅注册服务容器绑定"]
    D --> E["调用所有提供者的 boot()<br>View Composer、事件监听器等"]
    E --> F["应用准备就绪<br>开始处理请求"]
```

Laravel 内部使用大量服务提供者来启动邮件、队列、缓存等核心服务。这些提供者中的许多是「延迟」提供者，只有真正需要其提供的服务时才会加载，而不是每次请求都加载。

用户自定义的服务提供者需要在 `bootstrap/providers.php` 文件中注册。

<Info>
  想更深入了解 Laravel 如何处理请求，请参阅[请求生命周期](https://laravel.com/docs/lifecycle)文档。
</Info>

## 编写服务提供者

所有服务提供者都继承自 `Illuminate\Support\ServiceProvider`。大多数服务提供者会同时包含 `register` 与 `boot` 方法。

要生成新的提供者，请使用 `make:provider` Artisan 命令。Laravel 会自动在 `bootstrap/providers.php` 中注册新的提供者。

```shell theme={null}
php artisan make:provider RiakServiceProvider
```

### register 方法

在 `register` 方法中，仅应向[服务容器](/zh/service-container)进行绑定注册。请勿在 `register` 中注册事件监听器、路由或其他功能——因为此时可能会错误地使用尚未加载的服务提供者所提供的服务。

```php theme={null}
<?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 theme={null}
<?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](https://laravel.com/docs/views#view-composers)，请写在 `boot` 方法中。**该方法会在其他所有服务提供者都注册完毕之后调用**，因此可以访问框架已注册的所有服务。

```php theme={null}
<?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 () {
            // ...
        });
    }
}
```

<Warning>
  请勿混淆 `register` 与 `boot` 方法的作用。`register` 仅用于注册绑定，`boot` 用于初始化服务和其他准备工作。
</Warning>

#### boot 方法中的依赖注入

`boot` 方法也可以通过类型提示注入依赖。[服务容器](/zh/service-container)会自动注入所需的依赖。

```php theme={null}
use Illuminate\Contracts\Routing\ResponseFactory;

/**
 * 启动应用服务
 */
public function boot(ResponseFactory $response): void
{
    $response->macro('serialized', function (mixed $value) {
        // ...
    });
}
```

## 注册服务提供者

所有服务提供者都在 `bootstrap/providers.php` 文件中注册。该文件返回一个包含应用服务提供者类名的数组。

```php theme={null}
<?php

return [
    App\Providers\AppServiceProvider::class,
];
```

<Info>
  在 Laravel 13 中，不再使用 `config/app.php` 的 `providers` 数组，而是通过 `bootstrap/providers.php` 注册服务提供者。`make:provider` 命令会自动添加。
</Info>

运行 `make:provider` Artisan 命令时，Laravel 会自动在该文件里添加提供者。如果是手动创建的提供者类，请手动将其添加到数组中。

```php theme={null}
<?php

return [
    App\Providers\AppServiceProvider::class,
    App\Providers\ComposerServiceProvider::class,
];
```

## 创建自定义服务提供者

下面演示实际编写一个自定义服务提供者。

<Steps>
  <Step title="生成提供者">
    使用 Artisan 命令生成服务提供者。

    ```shell theme={null}
    php artisan make:provider PaymentServiceProvider
    ```
  </Step>

  <Step title="在 register 方法中绑定">
    在生成的提供者的 `register` 方法中编写绑定。

    ```php theme={null}
    <?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
        {
            // 如需启动时的处理，写在这里
        }
    }
    ```
  </Step>

  <Step title="注册到 bootstrap/providers.php">
    使用 `make:provider` 时会自动注册。若为手动创建，请添加：

    ```php theme={null}
    <?php

    return [
        App\Providers\AppServiceProvider::class,
        App\Providers\PaymentServiceProvider::class,
    ];
    ```
  </Step>
</Steps>

## 延迟提供者（Deferred Providers）

如果提供者只用于注册服务容器绑定，那么可以推迟该提供者的注册，直到真正需要绑定时才加载。通过延迟这类提供者的加载，就不会在每次请求时都从文件系统加载，从而提升性能。

```mermaid theme={null}
flowchart TD
    A["应用启动"] --> B["加载并初始化普通提供者"]
    B --> C["延迟提供者只记录<br>它所提供的服务列表"]
    C --> D["请求处理"]
    D --> E{{"是否请求了<br>延迟提供者的服务？"}}
    E -->|"否"| F["提供者不加载<br>节省内存与开销"]
    E -->|"是"| G["按需加载提供者"]
    G --> H["执行 register()"]
    H --> I["从容器中获取服务"]
```

要创建延迟提供者，请实现 `\Illuminate\Contracts\Support\DeferrableProvider` 接口并定义 `provides` 方法。`provides` 方法返回该提供者所注册的服务容器绑定。

```php theme={null}
<?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];
    }
}
```

<Tip>
  延迟提供者适合那些只在特定功能中使用（而非全局）的服务。避免加载不必要的服务，可以进一步优化性能。
</Tip>

## 下一步

<Card title="服务容器" icon="box" href="/zh/service-container">
  详细了解服务容器机制与绑定。
</Card>


## Related topics

- [请求生命周期](/zh/lifecycle.md)
- [Laravel 10 升级到 11](/zh/blog/upgrade-10-to-11.md)
- [Laravel Passport（OAuth2 服务器实现）](/zh/passport.md)
- [Laravel Socialite（社交登录）](/zh/socialite.md)
- [服务容器](/zh/service-container.md)
