サービスコンテナのバインド

前回の「サービスコンテナ」では、bind() メソッドを使ったバインド方法しか試しませんでしが、今回はもう2種類の方法を試してみます。

  • シングルトンとしてのバインド
  • 既存インスタンスのバインド


前回の復習(バインドとインスタンス取得)

app/Http/routes.php に以下のサンプルコードを追加しました。今回はこの続きとして進めます。

// app/Http/routes.php

/*
 *  Class
 */
interface SenderInterface {
    public function send($message);
}

class MailSender implements SenderInterface {
    public function send($message) {
        // ここで、メールでメッセージを送る

        return "メールで $message を送りました。";
    }
}

class BikeSender implements SenderInterface {
    public function send($message) {
        // ここで、バイクに乗ってメッセージを届ける

        return "バイク便で $message を届けました。";
    }
}

/*
 *  Binding
 */
$this->app->bind('sender', 'MailSender');  // ①

/*
 * Routes
 */
Route::get('send/{message?}', function($message = '合格通知') {
    $sender = $this->app->make('sender');  // ②

    return $sender->send($message);
});

① サービスコンテナ(Applicationクラス)に、bind() メソッドを使って、キー名で MailSenderクラスをバインド
② キー名でクラスのインスタンスを生成

※このサンプルではお手軽にサービスコンテナを試すために、クラス定義やサービスコンテナのバインド処理を全て routes.php に記述しています。本来はクラス定義は別ファイルに切り出し、バインド処理はサービスプロバイダーに記述すべきですのでご注意ください。


シングルトンとしてバインド

singleton() メソッドでバインドすると、何度コンテナが呼び出されても、同じインスタンスが返されます。

// app/Http/routes.php

...

/*
 *  Binding
 */
$this->app->bind('sender', 'MailSender');  // キー名を使って、クラスをバインド
$this->app->singleton('sender_single', 'MailSender'); // ① 追加

/*
 * Routes
 */

...

Route::get('not_singleton', function() {  // ② 追加
    $sender1 = $this->app->make('sender');
    $sender2 = $this->app->make('sender');

    if ($sender1 === $sender2) {
        return "シングルトンです。";
    }

    return "シングルトンではありません。";
});

Route::get('singleton', function() {  // ③ 追加
    $sender1 = $this->app->make('sender_single');   // ④
    $sender2 = $this->app->make('sender_single');

    if ($sender1 === $sender2) {
        return "シングルトンです。";
    }

    return "シングルトンではありません。";
});

① singleton() メソッドでサービスコンテナに登録します。

② シングルトンではないケースをチェックするサンプルを追加。「シングルトンではありません。」と表示されます。

③ シングルトンのケースをチェックするサンプルを追加。「シングルトンです。」と表示されます。

④ singleton() で登録した時のキー名でインスタンスを取得します。何度やっても同じインスタンスが返ってきます。


既存インスタンスのバインド

instance() メソッドを使って、既存のオブジェクトのインスタンスをバインドすることができます。

// app/Http/routes.php

...

/*
 *  Binding
 */

...

$instance = new MailSender();
$this->app->instance('sender_instance', $instance); // ① 追加

/*
 * Routes
 */

...

Route::get('instance', function() use ($instance) {   // ② 追加
    $sender = $this->app->make('sender_instance');    // ③

    if ($instance === $sender) {
        return "既存のインスタンスです。";
    }

    return "既存のインスタンスではありません。";
});

① instance() メソッドで既存インスタンスをサービスコンテナに登録します。

② 既存インスタンのケースをチェックするサンプルを追加。「既存のインスタンスです。」と表示されます。

③ instance() で登録した時のキー名でインスタンスを取得します。毎回同じインスタンスが返ってくるので、実質的にはシングルトンと同じです。


まとめ

今回はサービスコンテナにクラスをシングルトンとしてバインドする方法と既存のインスタンスをバインドする方法を試すことが出来ました。1回のリクエスト処理内で何度も利用するクラスをコンテナにバインドする場合には、singleton() やinstance() を利用するとパフォーマンスの向上につながります。

コメントを残す