Skip to content

サービスプロバイダ

イントロダクション

サービスプロバイダは、すべてのLaravelアプリケーションの初期起動の中心です。あなた自身のアプリケーション、そしてLaravelのコアサービスもすべて、サービスプロバイダを介して初期起動されます。

しかし、「初期起動」とは何を意味するのでしょうか?一般的に、登録を意味します。つまり、サービスコンテナのバインディング、イベントリスナー、ミドルウェア、さらにはルートの登録です。サービスプロバイダは、アプリケーションの設定の中心地です。

Laravelは、メーラー、キュー、キャッシュなどのコアサービスを初期起動するために、内部的に数十のサービスプロバイダを使用しています。これらのプロバイダの多くは「遅延」プロバイダであり、つまり、すべてのリクエストで読み込まれるのではなく、提供するサービスが実際に必要になったときにのみ読み込まれます。

すべてのユーザー定義のサービスプロバイダは、bootstrap/providers.phpファイルに登録されています。次のドキュメントでは、独自のサービスプロバイダを作成し、Laravelアプリケーションに登録する方法を学びます。

Note

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のサービスコンテナにまだ慣れていない場合は、そのドキュメントをチェックしてください。

bindingssingletonsプロパティ

サービスプロバイダが多くの単純なバインディングを登録する場合、bindingssingletonsプロパティを使用することを選択できます。フレームワークがサービスプロバイダを読み込むとき、これらのプロパティを自動的にチェックし、それらのバインディングを登録します。

<?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メソッド

では、サービスプロバイダ内でビューコンポーザを登録する必要がある場合はどうでしょうか?それは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,
];

make:provider Artisanコマンドを呼び出すと、Laravelは自動的に生成されたプロバイダをbootstrap/providers.phpファイルに追加します。ただし、プロバイダクラスを手動で作成した場合は、配列にプロバイダクラスを手動で追加する必要があります。

<?php

return [
    App\Providers\AppServiceProvider::class,
    App\Providers\ComposerServiceProvider::class, // [tl! add]
];

遅延プロバイダ

もし、プロバイダがサービスコンテナにバインディングを登録するだけである場合、その登録を遅延させることを選択できます。遅延読み込みされたプロバイダは、アプリケーションのパフォーマンスを向上させます。なぜなら、それはすべてのリクエストでファイルシステムから読み込まれるのではなく、登録されたバインディングのいずれかが実際に必要になったときにのみ読み込まれるからです。

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];
    }
}

ユーザーノート