Readouble

Laravel 11.x サービスコンテナ

イントロダクションIntroduction

Laravelサービスコンテナは、クラスの依存関係を管理し、依存注入を実行するための強力なツールです。依存の注入は、本質的にこれを意味する派手なフレーズです。クラスの依存は、コンストラクターまたは場合によっては「セッター」メソッドを介してクラスに「注入」されます。The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection. Dependency injection is a fancy phrase that essentially means this: class dependencies are "injected" into the class via the constructor or, in some cases, "setter" methods.

簡単な例を見てみましょう。Let's look at a simple example:

<?php

namespace App\Http\Controllers;

use App\Services\AppleMusic;
use Illuminate\View\View;

class PodcastController extends Controller
{
    /**
     * 新しいコントローラインスタンスの生成
     */
    public function __construct(
        protected AppleMusic $apple,
    ) {}

    /**
     * 指定ユーザーのプロフィールを表示
     */
    public function show(string $id): View
    {
        return view('podcasts.show', [
            'podcast' => $this->apple->findPodcast($id)
        ]);
    }
}

この例では、PodcastControllerはApple Musicなどのデータソースからポッドキャストを取得する必要があります。そこで、ポッドキャストを取得できるサービスを依存注入しています。サービスを依存注入することにより、アプリケーションをテストする際にAppleMusicサービスのダミー実装を簡単に作成できます。In this example, the PodcastController needs to retrieve podcasts from a data source such as Apple Music. So, we will inject a service that is able to retrieve podcasts. Since the service is injected, we are able to easily "mock", or create a dummy implementation of the AppleMusic service when testing our application.

Laravelサービスコンテナを深く理解することは、強力で大規模なアプリケーションを構築するため、およびLaravelコア自体に貢献するために不可欠です。A deep understanding of the Laravel service container is essential to building a powerful, large application, as well as for contributing to the Laravel core itself.

設定なしの依存解決Zero Configuration Resolution

クラスに依存関係がない場合、または他の具象クラス(インターフェイスではない)のみに依存している場合、そのクラスを依存解決する方法をコンテナへ指示する必要はありません。たとえば、以下のコードをroutes/web.phpファイルに配置できます。If a class has no dependencies or only depends on other concrete classes (not interfaces), the container does not need to be instructed on how to resolve that class. For example, you may place the following code in your routes/web.php file:

<?php

class Service
{
    // ...
}

Route::get('/', function (Service $service) {
    die($service::class);
});

この例でアプリケーションの/ルートを訪問すれば、自動的にServiceクラスが依存解決され、ルートのハンドラに依存挿入されます。これは大転換です。これは、アプリケーションの開発において、肥大化する設定ファイルの心配をせず依存注入を利用できることを意味します。In this example, hitting your application's / route will automatically resolve the Service class and inject it into your route's handler. This is game changing. It means you can develop your application and take advantage of dependency injection without worrying about bloated configuration files.

幸いに、Laravelアプリケーションを構築するときに作成するクラスの多くは、コントローライベントリスナミドルウェアなどのhandleメソッドにより依存関係を注入ができます。設定なしの自動的な依存注入の力を味わったなら、これなしに開発することは不可能だと思うことでしょう。Thankfully, many of the classes you will be writing when building a Laravel application automatically receive their dependencies via the container, including controllers[/docs/{{version}}/controllers], event listeners[/docs/{{version}}/events], middleware[/docs/{{version}}/middleware], and more. Additionally, you may type-hint dependencies in the handle method of queued jobs[/docs/{{version}}/queues]. Once you taste the power of automatic and zero configuration dependency injection it feels impossible to develop without it.

いつコンテナを使用するかWhen to Utilize the Container

幸運にも、依存解決の設定がいらないため、ルート、コントローラ、イベントリスナ、その他どこでも、コンテナを手作業で操作しなくても、依存関係を頻繁にタイプヒントできます。たとえば、現在のリクエストに簡単にアクセスできるように、ルート定義でIlluminate\Http\Requestオブジェクトをタイプヒントできます。このコードを書くため、コンテナを操作する必要はありません。コンテナはこうした依存関係の注入をバックグラウンドで管理しています。Thanks to zero configuration resolution, you will often type-hint dependencies on routes, controllers, event listeners, and elsewhere without ever manually interacting with the container. For example, you might type-hint the Illuminate\Http\Request object on your route definition so that you can easily access the current request. Even though we never have to interact with the container to write this code, it is managing the injection of these dependencies behind the scenes:

use Illuminate\Http\Request;

Route::get('/', function (Request $request) {
    // ...
});

多くの場合、自動依存注入とファサードのおかげで、コンテナから手作業で結合したり依存解決したりすることなく、Laravelアプリケーションを構築できます。**では、いつ手作業でコンテナを操作するのでしょう?**2つの状況を調べてみましょう。In many cases, thanks to automatic dependency injection and facades[/docs/{{version}}/facades], you can build Laravel applications without ever manually binding or resolving anything from the container. So, when would you ever manually interact with the container? Let's examine two situations.

第1に、インターフェイスを実装するクラスを作成し、そのインターフェイスをルートまたはクラスコンストラクターで型指定する場合は、コンテナにそのインターフェイスを解決する方法を指示する必要があります。第2に、他のLaravel開発者と共有する予定のLaravelパッケージの作成の場合、パッケージのサービスをコンテナに結合する必要がある場合があります。First, if you write a class that implements an interface and you wish to type-hint that interface on a route or class constructor, you must tell the container how to resolve that interface[#binding-interfaces-to-implementations]. Secondly, if you are writing a Laravel package[/docs/{{version}}/packages] that you plan to share with other Laravel developers, you may need to bind your package's services into the container.

結合Binding

結合の基本Binding Basics

シンプルな結合Simple Bindings

ほとんどすべてのサービスコンテナ結合はサービスプロバイダ内で登録されるため、こうした例のほとんどは、この状況でのコンテナの使用法になります。Almost all of your service container bindings will be registered within service providers[/docs/{{version}}/providers], so most of these examples will demonstrate using the container in that context.

サービスプロバイダ内では、常に$this->appプロパティを介してコンテナにアクセスできます。bindメソッドを使用して結合を登録しできます。登録するクラスまたはインターフェイス名を、クラスのインスタンスを返すクロージャとともに渡します。Within a service provider, you always have access to the container via the $this->app property. We can register a binding using the bind method, passing the class or interface name that we wish to register along with a closure that returns an instance of the class:

use App\Services\Transistor;
use App\Services\PodcastParser;
use Illuminate\Contracts\Foundation\Application;

$this->app->bind(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});

リゾルバの引数としてコンテナ自体を受け取ることに注意してください。そのコンテナを使用して、構築中のオブジェクトの依存関係を解決できるのです。Note that we receive the container itself as an argument to the resolver. We can then use the container to resolve sub-dependencies of the object we are building.

前述のように、通常はサービスプロバイダ内のコンテナの中で操作します。ただし、サービスプロバイダの外部でコンテナとやり取りする場合は、Appファサードを用いて操作します。As mentioned, you will typically be interacting with the container within service providers; however, if you would like to interact with the container outside of a service provider, you may do so via the App facade[/docs/{{version}}/facades]:

use App\Services\Transistor;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\App;

App::bind(Transistor::class, function (Application $app) {
    // ...
});

指定するタイプに対する結合がまだ登録されていない場合にのみ、コンテナ結合を登録するには、bindIfメソッドを使用してください。You may use the bindIf method to register a container binding only if a binding has not already been registered for the given type:

$this->app->bindIf(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});

lightbulb Note: クラスがどのインターフェイスにも依存しない場合、クラスをコンテナに結合する必要はありません。コンテナは、リフレクションを使用してこれらのオブジェクトを自動的に解決できるため、これらのオブジェクトの作成方法を指示する必要はありません。[!NOTE]
There is no need to bind classes into the container if they do not depend on any interfaces. The container does not need to be instructed on how to build these objects, since it can automatically resolve these objects using reflection.

シングルトンの結合Binding A Singleton

singletonメソッドは、クラスまたはインターフェイスをコンテナに結合しますが、これは1回のみ依存解決される必要がある結合です。シングルトン結合が依存解決されたら、コンテナに対する後続の呼び出しで、同じオブジェクトインスタンスが返されます。The singleton method binds a class or interface into the container that should only be resolved one time. Once a singleton binding is resolved, the same object instance will be returned on subsequent calls into the container:

use App\Services\Transistor;
use App\Services\PodcastParser;
use Illuminate\Contracts\Foundation\Application;

$this->app->singleton(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});

指定する型に対する結合がまだ登録されていない場合にのみ、シングルトンコンテナ結合を登録したい場合はsingletonIfメソッドを使用します。You may use the singletonIf method to register a singleton container binding only if a binding has not already been registered for the given type:

$this->app->singletonIf(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});

スコープ付きシングルトンの結合Binding Scoped Singletons

scopedメソッドは、Laravelのリクエストやジョブのライフサイクルの中で、一度だけ解決されるべきクラスやインターフェイスをコンテナへ結合します。このメソッドはsingletonメソッドと似ていますが、scopedメソッドを使って登録したインスタンスは、Laravelアプリケーションが新しい「ライフサイクル」を開始するたびにフラッシュされます。例えば、Laravel Octaneワーカが新しいリクエストを処理するときや、Laravel キューワーカが新しいジョブを処理するときなどです。The scoped method binds a class or interface into the container that should only be resolved one time within a given Laravel request / job lifecycle. While this method is similar to the singleton method, instances registered using the scoped method will be flushed whenever the Laravel application starts a new "lifecycle", such as when a Laravel Octane[/docs/{{version}}/octane] worker processes a new request or when a Laravel queue worker[/docs/{{version}}/queues] processes a new job:

use App\Services\Transistor;
use App\Services\PodcastParser;
use Illuminate\Contracts\Foundation\Application;

$this->app->scoped(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});

指定タイプの結合がまだ登録されていない場合のみ、スコープ付きコンテナ結合を登録するには、scopedIfメソッドを使用します。You may use the scopedIf method to register a scoped container binding only if a binding has not already been registered for the given type:

$this->app->scopedIf(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});

インスタンスの結合Binding Instances

instanceメソッドを使用して、既存のオブジェクトインスタンスをコンテナへ結合することもできます。指定したインスタンスは、コンテナに対する後続の呼び出しで常に返されます。You may also bind an existing object instance into the container using the instance method. The given instance will always be returned on subsequent calls into the container:

use App\Services\Transistor;
use App\Services\PodcastParser;

$service = new Transistor(new PodcastParser);

$this->app->instance(Transistor::class, $service);

インターフェイスと実装の結合Binding Interfaces to Implementations

サービスコンテナの非常に強力な機能は、インターフェイスを特定の実装に結合する機能です。たとえば、EventPusherインターフェイスとRedisEventPusher実装があると仮定しましょう。このインターフェイスのRedisEventPusher実装をコーディングしたら、次のようにサービスコンテナに登録できます。A very powerful feature of the service container is its ability to bind an interface to a given implementation. For example, let's assume we have an EventPusher interface and a RedisEventPusher implementation. Once we have coded our RedisEventPusher implementation of this interface, we can register it with the service container like so:

use App\Contracts\EventPusher;
use App\Services\RedisEventPusher;

$this->app->bind(EventPusher::class, RedisEventPusher::class);

この文は、クラスがEventPusherの実装を必要とするときに、RedisEventPusherを注入する必要があることをコンテナに伝えています。これで、コンテナにより依存解決されるクラスのコンストラクタでEventPusherインターフェイスをタイプヒントできます。Laravelアプリケーション内のコントローラ、イベントリスナ、ミドルウェア、およびその他のさまざまなタイプのクラスは、常にコンテナを使用して解決されることを忘れないでください。This statement tells the container that it should inject the RedisEventPusher when a class needs an implementation of EventPusher. Now we can type-hint the EventPusher interface in the constructor of a class that is resolved by the container. Remember, controllers, event listeners, middleware, and various other types of classes within Laravel applications are always resolved using the container:

use App\Contracts\EventPusher;

/**
 * 新しいクラスインスタンスの生成
 */
public function __construct(
    protected EventPusher $pusher,
) {}

コンテキストによる結合Contextual Binding

同じインターフェイスを利用する2つのクラスがある場合、各クラスに異なる実装を依存注入したい場合があります。たとえば、2つのコントローラは、Illuminate\Contracts\Filesystem\Filesystem契約の異なる実装に依存する場合があります。Laravelは、この動作を定義するためのシンプルで流暢なインターフェイスを提供します。Sometimes you may have two classes that utilize the same interface, but you wish to inject different implementations into each class. For example, two controllers may depend on different implementations of the Illuminate\Contracts\Filesystem\Filesystem contract[/docs/{{version}}/contracts]. Laravel provides a simple, fluent interface for defining this behavior:

use App\Http\Controllers\PhotoController;
use App\Http\Controllers\UploadController;
use App\Http\Controllers\VideoController;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Facades\Storage;

$this->app->when(PhotoController::class)
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('local');
          });

$this->app->when([VideoController::class, UploadController::class])
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('s3');
          });

コンテキスト属性Contextual Attributes

コンテキストによる結合は、ドライバの実装や設定値のインジェクションに使用されることが多いため、Laravelでは、サービスプロバイダでコンテキストによる結合を手作業で定義しなくても、こうしたタイプの値を注入できるように、様々なコンテキストによる結合属性を提供しています。Since contextual binding is often used to inject implementations of drivers or configuration values, Laravel offers a variety of contextual binding attributes that allow to inject these types of values without manually defining the contextual bindings in your service providers.

例えば、Storage属性は特定のストレージディスクを注入するために使用できます。For example, the Storage attribute may be used to inject a specific storage disk[/docs/{{version}}/filesystem]:

<?php

namespace App\Http\Controllers;

use Illuminate\Container\Attributes\Storage;
use Illuminate\Contracts\Filesystem\Filesystem;

class PhotoController extends Controller
{
    public function __construct(
        #[Storage('local')] protected Filesystem $filesystem
    )
    {
        // ...
    }
}

Storage属性の他に、AuthCacheConfigDBLogRouteParameterTag属性をLaravelは用意しています。In addition to the Storage attribute, Laravel offers Auth, Cache, Config, DB, Log, RouteParameter, and Tag[#tagging] attributes:

<?php

namespace App\Http\Controllers;

use Illuminate\Container\Attributes\Auth;
use Illuminate\Container\Attributes\Cache;
use Illuminate\Container\Attributes\Config;
use Illuminate\Container\Attributes\DB;
use Illuminate\Container\Attributes\Log;
use Illuminate\Container\Attributes\Tag;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Cache\Repository;
use Illuminate\Contracts\Database\Connection;
use Psr\Log\LoggerInterface;

class PhotoController extends Controller
{
    public function __construct(
        #[Auth('web')] protected Guard $auth,
        #[Cache('redis')] protected Repository $cache,
        #[Config('app.timezone')] protected string $timezone,
        #[DB('mysql')] protected Connection $connection,
        #[Log('daily')] protected LoggerInterface $log,
        #[Tag('reports')] protected iterable $reports,
    )
    {
        // ...
    }
}

さらに、Laravelは現在の認証済みユーザーを指定ルートやクラスへ注入するために、CurrentUser属性を提供しています。Furthermore, Laravel provides a CurrentUser attribute for injecting the currently authenticated user into a given route or class:

use App\Models\User;
use Illuminate\Container\Attributes\CurrentUser;

Route::get('/user', function (#[CurrentUser] User $user) {
    return $user;
})->middleware('auth');

カスタム属性の定義Defining Custom Attributes

Illuminate\Contracts\Container\ContextualAttribute契約を実装すれば、独自のコンテキスト属性が作成できます。コンテナは属性のresolveメソッドを呼び出し、属性を利用するクラスへ注入する値を解決します。以下の例では、Laravelの組み込みのConfig属性を再実装しています。You can create your own contextual attributes by implementing the Illuminate\Contracts\Container\ContextualAttribute contract. The container will call your attribute's resolve method, which should resolve the value that should be injected into the class utilizing the attribute. In the example below, we will re-implement Laravel's built-in Config attribute:

<?php

namespace App\Attributes;

use Illuminate\Contracts\Container\ContextualAttribute;

#[Attribute(Attribute::TARGET_PARAMETER)]
class Config implements ContextualAttribute
{
    /**
     * 新属性インスタンスの生成
     */
    public function __construct(public string $key, public mixed $default = null)
    {
    }

    /**
     * 設定値の解決
     *
     * @param  self  $attribute
     * @param  \Illuminate\Contracts\Container\Container  $container
     * @return mixed
     */
    public static function resolve(self $attribute, Container $container)
    {
        return $container->make('config')->get($attribute->key, $attribute->default);
    }
}

プリミティブの結合Binding Primitives

注入されたクラスを受け取るだけでなく、整数などのプリミティブ値も注入され、受け取るクラスがときにはあるでしょう。コンテキストによる結合を使用して、クラスへ必要な値を簡単に依存注入できます。Sometimes you may have a class that receives some injected classes, but also needs an injected primitive value such as an integer. You may easily use contextual binding to inject any value your class may need:

use App\Http\Controllers\UserController;

$this->app->when(UserController::class)
          ->needs('$variableName')
          ->give($value);

クラスがタグ付きインスタンスの配列へ依存する場合があります。giveTaggedメソッドを使用すると、そのタグを使用してすべてのコンテナバインディングを簡単に挿入できます。Sometimes a class may depend on an array of tagged[#tagging] instances. Using the giveTagged method, you may easily inject all of the container bindings with that tag:

$this->app->when(ReportAggregator::class)
    ->needs('$reports')
    ->giveTagged('reports');

アプリケーションの設定ファイルの1つから値を注入する必要がある場合は、giveConfigメソッドを使用します。If you need to inject a value from one of your application's configuration files, you may use the giveConfig method:

$this->app->when(ReportAggregator::class)
    ->needs('$timezone')
    ->giveConfig('app.timezone');

型指定した可変引数の結合Binding Typed Variadics

時折、可変コンストラクター引数を使用して型付きオブジェクトの配列を受け取るクラスが存在する場合があります。Occasionally, you may have a class that receives an array of typed objects using a variadic constructor argument:

<?php

use App\Models\Filter;
use App\Services\Logger;

class Firewall
{
    /**
     * フィルタインスタンス
     *
     * @var array
     */
    protected $filters;

    /**
     * 新しいクラスインスタンスの生成
     */
    public function __construct(
        protected Logger $logger,
        Filter ...$filters,
    ) {
        $this->filters = $filters;
    }
}

文脈による結合を使用すると、依存解決したFilterインスタンスの配列を返すクロージャをgiveメソッドへ渡すことで、この依存関係を解決できます。Using contextual binding, you may resolve this dependency by providing the give method with a closure that returns an array of resolved Filter instances:

$this->app->when(Firewall::class)
          ->needs(Filter::class)
          ->give(function (Application $app) {
                return [
                    $app->make(NullFilter::class),
                    $app->make(ProfanityFilter::class),
                    $app->make(TooLongFilter::class),
                ];
          });

利便性のため、いつでもFirewallFilterインスタンスを必要とするときは、コンテナが解決するクラス名の配列も渡せます。For convenience, you may also just provide an array of class names to be resolved by the container whenever Firewall needs Filter instances:

$this->app->when(Firewall::class)
          ->needs(Filter::class)
          ->give([
              NullFilter::class,
              ProfanityFilter::class,
              TooLongFilter::class,
          ]);

可変引数タグの依存Variadic Tag Dependencies

クラスには、特定のクラスとしてタイプヒントされた可変引数の依存関係を持つ場合があります(Report ...$reports)。needsメソッドとgiveTaggedメソッドを使用すると、特定の依存関係に対して、そのtagを使用してすべてのコンテナ結合を簡単に挿入できます。Sometimes a class may have a variadic dependency that is type-hinted as a given class (Report ...$reports). Using the needs and giveTagged methods, you may easily inject all of the container bindings with that tag[#tagging] for the given dependency:

$this->app->when(ReportAggregator::class)
    ->needs(Report::class)
    ->giveTagged('reports');

タグ付けTagging

場合により、特定の結合「カテゴリ」をすべて依存解決する必要が起きます。たとえば、さまざまなReportインターフェイス実装の配列を受け取るレポートアナライザを構築しているとしましょう。Report実装を登録した後、tagメソッドを使用してそれらにタグを割り当てられます。Occasionally, you may need to resolve all of a certain "category" of binding. For example, perhaps you are building a report analyzer that receives an array of many different Report interface implementations. After registering the Report implementations, you can assign them a tag using the tag method:

$this->app->bind(CpuReport::class, function () {
    // ...
});

$this->app->bind(MemoryReport::class, function () {
    // ...
});

$this->app->tag([CpuReport::class, MemoryReport::class], 'reports');

サービスにタグ付けしたら、コンテナのtaggedメソッドを使用して簡単にすべてを依存解決できます。Once the services have been tagged, you may easily resolve them all via the container's tagged method:

$this->app->bind(ReportAnalyzer::class, function (Application $app) {
    return new ReportAnalyzer($app->tagged('reports'));
});

結合の拡張Extending Bindings

extendメソッドを使用すると、依存解決済みのサービスを変更できます。たとえば、サービスを依存解決した後、追加のコードを実行してサービスをデコレートまたは設定できます。extendメソッドは拡張するサービスクラスと、変更したサービスを返すクロージャの2引数を取ります。クロージャは解決するサービスとコンテナインスタンスを引数に取ります。The extend method allows the modification of resolved services. For example, when a service is resolved, you may run additional code to decorate or configure the service. The extend method accepts two arguments, the service class you're extending and a closure that should return the modified service. The closure receives the service being resolved and the container instance:

$this->app->extend(Service::class, function (Service $service, Application $app) {
    return new DecoratedService($service);
});

依存解決Resolving

makeメソッドThe make Method

makeメソッドを使用して、コンテナからクラスインスタンスを解決します。makeメソッドは、解決したいクラスまたはインターフェイスの名前を受け入れます。You may use the make method to resolve a class instance from the container. The make method accepts the name of the class or interface you wish to resolve:

use App\Services\Transistor;

$transistor = $this->app->make(Transistor::class);

クラスの依存関係の一部がコンテナを介して解決できない場合は、それらを連想配列としてmakeWithメソッドに渡すことでそれらを依存注入できます。たとえば、Transistorサービスに必要な$idコンストラクタ引数を手作業で渡すことができます。If some of your class's dependencies are not resolvable via the container, you may inject them by passing them as an associative array into the makeWith method. For example, we may manually pass the $id constructor argument required by the Transistor service:

use App\Services\Transistor;

$transistor = $this->app->makeWith(Transistor::class, ['id' => 1]);

boundメソッドは、クラスやインターフェイスをコンテナ内で明示的に結合しているかを判定するために使用します。The bound method may be used to determine if a class or interface has been explicitly bound in the container:

if ($this->app->bound(Transistor::class)) {
    // ...
}

サービスプロバイダの外部で、$app変数にアクセスできないコードの場所では、Appファサードappヘルパを使用してコンテナからクラスインスタンスを依存解決します。If you are outside of a service provider in a location of your code that does not have access to the $app variable, you may use the App facade[/docs/{{version}}/facades] or the app helper[/docs/{{version}}/helpers#method-app] to resolve a class instance from the container:

use App\Services\Transistor;
use Illuminate\Support\Facades\App;

$transistor = App::make(Transistor::class);

$transistor = app(Transistor::class);

Laravelコンテナインスタンス自体をコンテナにより解決中のクラスへ依存注入したい場合は、クラスのコンストラクタでIlluminate\Container\Containerクラスを入力してください。If you would like to have the Laravel container instance itself injected into a class that is being resolved by the container, you may type-hint the Illuminate\Container\Container class on your class's constructor:

use Illuminate\Container\Container;

/**
 * 新しいクラスインスタンスの生成
 */
public function __construct(
    protected Container $container,
) {}

自動注入Automatic Injection

あるいは、そして重要なことに、コントローライベントリスナミドルウェアなど、コンテナにより解決されるクラスのコンストラクターでは、依存関係をタイプヒントすることができます。さらに、キュー投入するジョブhandleメソッドでも、依存関係をタイプヒントできます。実践的に、ほとんどのオブジェクトはコンテナにより解決されるべきでしょう。Alternatively, and importantly, you may type-hint the dependency in the constructor of a class that is resolved by the container, including controllers[/docs/{{version}}/controllers], event listeners[/docs/{{version}}/events], middleware[/docs/{{version}}/middleware], and more. Additionally, you may type-hint dependencies in the handle method of queued jobs[/docs/{{version}}/queues]. In practice, this is how most of your objects should be resolved by the container.

たとえば、コントローラのコンストラクタでアプリケーションが定義したサービスをタイプヒントすることができます。そのサービスを自動的に解決し、クラスに依存注入します。For example, you may type-hint a service defined by your application in a controller's constructor. The service will automatically be resolved and injected into the class:

<?php

namespace App\Http\Controllers;

use App\Services\AppleMusic;

class PodcastController extends Controller
{
    /**
     * 新しいコントローラインスタンスの生成
     */
    public function __construct(
        protected AppleMusic $apple,
    ) {}

    /**
     * 指定ポッドキャストの情報を表示
     */
    public function show(string $id): Podcast
    {
        return $this->apple->findPodcast($id);
    }
}

メソッドの起動と依存注入Method Invocation and Injection

コンテナがあるメソッドの依存関係を自動的に注入できるようにしたまま、そのオブジェクトインスタンス上のメソッドを起動したい場合があります。たとえば、以下のクラスを想定してください。Sometimes you may wish to invoke a method on an object instance while allowing the container to automatically inject that method's dependencies. For example, given the following class:

<?php

namespace App;

use App\Services\AppleMusic;

class PodcastStats
{
    /**
     * 新しいポッドキャストの状況レポートを生成
     */
    public function generate(AppleMusic $apple): array
    {
        return [
            // ...
        ];
    }
}

次のように、コンテナを介してgenerateメソッドを呼び出せます。You may invoke the generate method via the container like so:

use App\PodcastStats;
use Illuminate\Support\Facades\App;

$stats = App::call([new PodcastStats, 'generate']);

callメソッドは任意のPHP callableを受け入れます。コンテナのcallメソッドは、依存関係を自動的に注入しながら、クロージャを呼び出すためにも使用できます。The call method accepts any PHP callable. The container's call method may even be used to invoke a closure while automatically injecting its dependencies:

use App\Services\AppleMusic;
use Illuminate\Support\Facades\App;

$result = App::call(function (AppleMusic $apple) {
    // ...
});

コンテナイベントContainer Events

サービスコンテナは、オブジェクトを依存解決するたびにイベントを発生させます。resolvingメソッドを使用してこのイベントをリッスンできます。The service container fires an event each time it resolves an object. You may listen to this event using the resolving method:

use App\Services\Transistor;
use Illuminate\Contracts\Foundation\Application;

$this->app->resolving(Transistor::class, function (Transistor $transistor, Application $app) {
    // コンテナがTransistorタイプのオブジェクトを解決するときに呼び出される
});

$this->app->resolving(function (mixed $object, Application $app) {
    // コンテナが任意のタイプのオブジェクトを解決するときに呼び出される
});

ご覧のとおり、解決しているオブジェクトがコールバックに渡され、利用側に渡される前にオブジェクトへ追加のプロパティを設定できます。As you can see, the object being resolved will be passed to the callback, allowing you to set any additional properties on the object before it is given to its consumer.

再インデックスRebinding

rebindingメソッドを使用すると、サービスがコンテナに再結合されたとき、つまり最初の結合の後に再度登録されたりオーバーライドされたりしたときをリッスンできます。これは、特定の結合が更新されるたびに依存関係を更新したり、動作を変更したりする必要がある場合に便利です。The rebinding method allows you to listen for when a service is re-bound to the container, meaning it is registered again or overridden after its initial binding. This can be useful when you need to update dependencies or modify behavior each time a specific binding is updated:

use App\Contracts\PodcastPublisher;
use App\Services\SpotifyPublisher;
use App\Services\TransistorPublisher;
use Illuminate\Contracts\Foundation\Application;

$this->app->bind(PodcastPublisher::class, SpotifyPublisher::class);

$this->app->rebinding(
    PodcastPublisher::class,
    function (Application $app, PodcastPublisher $newInstance) {
        //
    },
);

// この新しい結合は、再インデックスクロージャを起動する
$this->app->bind(PodcastPublisher::class, TransistorPublisher::class);

PSR-11PSR-11

Laravelのサービスコンテナは、PSR-11インターフェイスを実装しています。したがって、PSR-11コンテナインターフェイスをタイプヒントして、Laravelコンテナのインスタンスを取得できます。Laravel's service container implements the PSR-11[https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md] interface. Therefore, you may type-hint the PSR-11 container interface to obtain an instance of the Laravel container:

use App\Services\Transistor;
use Psr\Container\ContainerInterface;

Route::get('/', function (ContainerInterface $container) {
    $service = $container->get(Transistor::class);

    // ...
});

指定した識別子を解決できない場合は例外を投げます。識別子が結合されなかった場合、例外はPsr\Container\NotFoundExceptionInterfaceのインスタンスです。識別子が結合されているが依存解決できなかった場合、Psr\Container\ContainerExceptionInterfaceのインスタンスを投げます。An exception is thrown if the given identifier can't be resolved. The exception will be an instance of Psr\Container\NotFoundExceptionInterface if the identifier was never bound. If the identifier was bound but was unable to be resolved, an instance of Psr\Container\ContainerExceptionInterface will be thrown.

章選択

設定

明暗テーマ
light_mode
dark_mode
brightness_auto システム設定に合わせる
テーマ選択
photo_size_select_actual デフォルト
photo_size_select_actual モノクローム(白黒)
photo_size_select_actual Solarized風
photo_size_select_actual GitHub風(青ベース)
photo_size_select_actual Viva(黄緑ベース)
photo_size_select_actual Happy(紫ベース)
photo_size_select_actual Mint(緑ベース)
コードハイライトテーマ選択

明暗テーマごとに、コードハイライトのテーマを指定できます。

テーマ配色確認
スクリーン表示幅
640px
80%
90%
100%

768px以上の幅があるときのドキュメント部分表示幅です。

インデント
無し
1rem
2rem
3rem
原文確認
原文を全行表示
原文を一行ずつ表示
使用しない

※ 段落末のEボタンへカーソルオンで原文をPopupします。

Diff表示形式
色分けのみで区別
行頭の±で区別
削除線と追記で区別

※ [tl!…]形式の挿入削除行の表示形式です。

テストコード表示
両コード表示
Pestのみ表示
PHPUnitのみ表示
OS表示
全OS表示
macOSのみ表示
windowsのみ表示
linuxのみ表示
和文変換

対象文字列と置換文字列を半角スペースで区切ってください。(最大5組各10文字まで)

本文フォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

コードフォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

保存内容リセット

localStrageに保存してある設定項目をすべて削除し、デフォルト状態へ戻します。

ヘッダー項目移動

キーボード操作