Skip to content
虚位以待
赞助商
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待

服务提供者

介绍

服务提供者是所有 Laravel 应用程序引导的中心位置。您自己的应用程序以及所有 Laravel 的核心服务,都是通过服务提供者引导的。

但是,我们所说的“引导”是什么意思呢?一般来说,我们指的是 注册 事物,包括注册服务容器绑定、事件监听器、中间件,甚至路由。服务提供者是配置您应用程序的中心位置。

如果您打开与 Laravel 一起提供的 config/app.php 文件,您将看到一个 providers 数组。这些都是将为您的应用程序加载的服务提供者类。默认情况下,Laravel 核心服务提供者的集合列在此数组中。这些提供者引导核心 Laravel 组件,例如邮件、队列、缓存等。许多这些提供者是“延迟”提供者,这意味着它们不会在每个请求中加载,而仅在实际需要它们提供的服务时加载。

在本概述中,您将学习如何编写自己的服务提供者并将其注册到您的 Laravel 应用程序中。

NOTE

如果您想了解更多关于 Laravel 如何处理请求和内部工作的信息,请查看我们关于 Laravel 请求生命周期 的文档。

编写服务提供者

所有服务提供者都扩展了 Illuminate\Support\ServiceProvider 类。大多数服务提供者包含 registerboot 方法。在 register 方法中,您应该 仅将事物绑定到 服务容器。您不应尝试在 register 方法中注册任何事件监听器、路由或任何其他功能。

Artisan CLI 可以通过 make:provider 命令生成一个新的提供者:

shell
php artisan make:provider RiakServiceProvider

注册方法

如前所述,在 register 方法中,您应该仅将事物绑定到 服务容器。您不应尝试在 register 方法中注册任何事件监听器、路由或任何其他功能。否则,您可能会意外使用尚未加载的服务提供者提供的服务。

让我们看一下一个基本的服务提供者。在您的任何服务提供者方法中,您始终可以访问 $app 属性,该属性提供对服务容器的访问:

php
<?php

namespace App\Providers;

use App\Services\Riak\Connection;
use Illuminate\Support\ServiceProvider;

class RiakServiceProvider extends ServiceProvider
{
    /**
     * 注册任何应用程序服务。
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection(config('riak'));
        });
    }
}

这个服务提供者仅定义了一个 register 方法,并使用该方法在服务容器中定义 App\Services\Riak\Connection 的实现。如果您还不熟悉 Laravel 的服务容器,请查看 其文档

bindingssingletons 属性

如果您的服务提供者注册了许多简单的绑定,您可能希望使用 bindingssingletons 属性,而不是手动注册每个容器绑定。当框架加载服务提供者时,它将自动检查这些属性并注册它们的绑定:

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
{
    /**
     * 所有应注册的容器绑定。
     *
     * @var array
     */
    public $bindings = [
        ServerProvider::class => DigitalOceanServerProvider::class,
    ];

    /**
     * 所有应注册的容器单例。
     *
     * @var array
     */
    public $singletons = [
        DowntimeNotifier::class => PingdomDowntimeNotifier::class,
        ServerProvider::class => ServerToolsProvider::class,
    ];
}

引导方法

那么,如果我们需要在服务提供者中注册一个 视图作曲家 呢?这应该在 boot 方法中完成。此方法在所有其他服务提供者注册后被调用,这意味着您可以访问框架注册的所有其他服务:

php
<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{
    /**
     * 引导任何应用程序服务。
     *
     * @return void
     */
    public function boot()
    {
        View::composer('view', function () {
            //
        });
    }
}

引导方法依赖注入

您可以为服务提供者的 boot 方法类型提示依赖项。服务容器 将自动注入您所需的任何依赖项:

php
use Illuminate\Contracts\Routing\ResponseFactory;

/**
 * 引导任何应用程序服务。
 *
 * @param  \Illuminate\Contracts\Routing\ResponseFactory  $response
 * @return void
 */
public function boot(ResponseFactory $response)
{
    $response->macro('serialized', function ($value) {
        //
    });
}

注册提供者

所有服务提供者都在 config/app.php 配置文件中注册。此文件包含一个 providers 数组,您可以在其中列出服务提供者的类名。默认情况下,Laravel 核心服务提供者的集合列在此数组中。这些提供者引导核心 Laravel 组件,例如邮件、队列、缓存等。

要注册您的提供者,请将其添加到数组中:

php
'providers' => [
    // 其他服务提供者

    App\Providers\ComposerServiceProvider::class,
],

延迟提供者

如果您的提供者 服务容器 中注册绑定,您可以选择延迟其注册,直到实际需要其中一个注册的绑定。延迟加载这样的提供者将提高您应用程序的性能,因为它不会在每个请求中从文件系统加载。

Laravel 编译并存储所有延迟服务提供者提供的服务的列表,以及其服务提供者类的名称。然后,只有在您尝试解析其中一个服务时,Laravel 才会加载服务提供者。

要延迟加载提供者,请实现 \Illuminate\Contracts\Support\DeferrableProvider 接口并定义 provides 方法。provides 方法应返回由提供者注册的服务容器绑定:

php
<?php

namespace App\Providers;

use App\Services\Riak\Connection;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;

class RiakServiceProvider extends ServiceProvider implements DeferrableProvider
{
    /**
     * 注册任何应用程序服务。
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection($app['config']['riak']);
        });
    }

    /**
     * 获取提供者提供的服务。
     *
     * @return array
     */
    public function provides()
    {
        return [Connection::class];
    }
}