LoginSignup
6
2

【Laravel】 サービスコンテナとは、使い方や解説

Posted at

サービスコンテナとは

たくさんのサービスを入れておく箱という認識でOK(クラスをインスタンス化してくれる箱)

箱に入れる方法

app()->bind()

で箱に登録したり

箱の中から取り出す

app()->make()

で箱の中から取り出したりをする事ができます。

実際にコードを書いた方が理解が深まると思いますので進めていきましょう。

環境

laravel8
Windows11

サービスコンテナの使い方

ルーティングの作成

最初にルーティングファイルから作ることにします。

routes > web.php

use App\Http\Controllers\LifeCycleController;

Route::get('/container', [LifeCycleController::class, 'showServiceContainer']);

web.phpに記述する事ができたらコントローラーを作成していきます。

コントローラーの作成

次にターミナルで以下を実行してコントローラーを作成していきます。

php artisan make:controller LifeCycleController

上で作成したLifeCycleControllerは以下の場所に作成されます。

app > Http > Controllers > LifeCycleController

上のコントローラーが確認できたらOKです!

サービスコンテナの中身を確認

app()のヘルパ関数を使うと中身を確認できるので、dd()app()の中身を見てみましょう。

class LifeCycleController extends Controller
{
    public function showServiceContainer()
    {
        dd(app());
    }
}

この状態でweb.phpに記述したURLを簡易サーバーで確認すると以下のようにapp()の中身が確認する事ができます。

20230704_01.png

上のIlluminate\Foundation\Applicationの中にあるbindings:``array:71 [▶]は、サービスコンテナに登録されているサービスの数を表しています。実際に中身を確認すると様々なサービスがあることが確認できます。

まずは簡単にサービスコンテナにサービスを登録するということをやってみます。

サービスコンテナにサービスを登録する方法

登録する方法は、

app()->bind('lifeCycle', function()
{
   return 'ライフサイクルのテスト';
});

app()ヘルパ関数にbind()というメソッドで登録する事ができます。

登録した後に呼び出す名前を付ける必要があるので、今回はbind()の第一引数に記述されている lifeCycle で登録していきます。

bind()の第二引数で実行する内容を書いていきます。今回はライフサイクルのテストという文字を返すという内容でやっていきます。

実際にコードを書く

上で説明したようにコントローラーに書いていきます。

app > Http > Controllers > LifeCycleController

class LifeCycleController extends Controller
{
    public function showServiceContainer()
    {
        app()->bind('lifeCycle', function()
        {
            return 'ライフサイクルのテスト';
        });
        dd(app());
    }
}

上のように書くことができたらブラウザの画面で確認してみましょう。以下のように表示されていればOK!

20230704_02.png

先ほどまでは、上のIlluminate\Foundation\Applicationの中にあるbindings:``array:72 [▶]71だったのですが72に増えていることがわかります。

それでは上で追加したサービスコンテナから取り出してみましょう。

サービスコンテナから取り出す

サービスコンテナから取り出す場合は

app()->make('lifeCycle')

app()ヘルパ関数にmake()として引数に先ほどbind()の第一引数で設定したlifeCycleとしてあげれば取り出す事ができます。

実際にコードを書く

上で説明したようにコントローラーに書いていきます。

app > Http > Controllers > LifeCycleController

class LifeCycleController extends Controller
{
    public function showServiceContainer()
    {
        app()->bind('lifeCycle', function()
        {
            return 'ライフサイクルのテスト';
        });

        $test = app()->make('lifeCycle'); //追加
        dd($test, app()); //ddの中に$testを追加
    }
}

上のように書くことができたらブラウザの画面で確認してみましょう。以下のように表示されていればOK!

20230704_03.png

実際にbind()で登録したライフサイクルのテストという文字が呼び出されているのがわかります。

依存関係の解決

サービスコンテナの中でも重要な機能として依存関係の解決という機能があります。

依存関係の解決について

依存した2つ以上のクラスを使う時に

以下のように普通のPHPであればそれぞれのクラスをnewでインスタンス化して読み込み実行する必要があります。

$test = new Test();
$sample = new Sample($test);
$sample->run();

ですが、サービスコンテナを使用すればapp()→baind()で紐づけてapp()→make()で使用する際に、依存しているクラスも同時にインスタンス化してくれます。

なのでnewでインスタンス化しなくても使用できるのです。

app()->bind('sample',Sample::class);
$sample = app()->make('sample');
$sample->run();

使い方の説明

class Sample
{
    public $message;

    public function __construct(Message $message)
    {
        $this->message = $message;
    }

    public function run()
    {
        $this->message->send();
    }
}

class Message
{
    public function send()
    {
        echo('メッセージ');
    }
}

2つのクラスMessageSampleを作成します。

class Messageは、echoでメッセージを表示しているだけ

class Sampleは、__constructMessageクラスを読み込んでrun()メソッドの中でMessageクラスのsend()メソッドを設定しています。

実際にコードを書く

上で作成したコントローラー(LifeCycleController)を使用していきます。

※本来なら1ファイルに1クラスなのですが今回は分かりやすい使い方ということでLifeCycleControllerに複数のクラスを書いています。

class Message

まずはMessageクラスから書いていきます。

app > Http > Controllers > LifeCycleController

class Message
{
    public function send()
    {
        echo('メッセージ');
    }
}

class Sample

次にSampleクラスを書いていきます。

app > Http > Controllers > LifeCycleController

class Sample
{
    public $message;

    public function __construct(Message $message)
    {
        $this->message = $message;
    }

    public function run()
    {
        $this->message->send();
    }
}

プロパティでpublic $message;を書いて

インスタンス化する時にMessageも読み込みたいので__construct(Message $message)という書きかたで読み込みます。「これは、DIと呼ばれる仕組みで__construct()の引数にクラスを入れてあげると自動的にインスタンス化してくれます。」

$this->messageをしてあげるとMessageクラスがmessageに入ります。

$this->message->send();と書きMessageクラスのsend()メソッドを使用できるようにしています。

今回はSampleクラスの方で__construct()で初期化する時にMessageクラスも使うというようにしているのでSampleクラスを使う場合には、あらかじめMessageクラスをインスタンス化しておく必要があります。

class LifeCycleController

app > Http > Controllers > LifeCycleController

class LifeCycleController extends Controller
{
    public function showServiceContainer()
    {
        app()->bind('lifeCycle', function()
        {
            return 'ライフサイクルのテスト';
        });

        $test = app()->make('lifeCycle');

        app()->bind('sample', Sample::class); //追加
        $sample = app()->make('sample'); //追加
        $sample->run(); //追加

        dd($test, app());
    }
}

app()->bind()で紐づける際に、呼び出す名前を引数につける必要があるので、'sample'としておきます。今回はクラスを付けるので、Sample::classと書くことでSampleクラスを紐づける事ができます。

続いてapp()->make('sample');として呼び出してSampleの中にあるrun()メソッドを表示させます。

以下のように表示されていればOKです!

出力結果
メッセージ

コントローラー全体のコード

app > Http > Controllers > LifeCycleController

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class LifeCycleController extends Controller
{
    public function showServiceContainer()
    {
        app()->bind('lifeCycle', function()
        {
            return 'ライフサイクルのテスト';
        });

        $test = app()->make('lifeCycle');

        app()->bind('sample', Sample::class); //追加
        $sample = app()->make('sample'); //追加
        $sample->run(); //追加

        dd($test, app());
    }
}
//以下すべて追加

class Sample
{
    public $message;

    public function __construct(Message $message)
    {
        $this->message = $message;
    }

    public function run()
    {
        $this->message->send();
    }
}

class Message
{
    public function send()
    {
        echo('メッセージ');
    }
}

以上

上のことを理解することでLaravelに書かれているコードがかなり読みやすくなると思うので覚えておくとかなり良いと思います!

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2