読者です 読者をやめる 読者になる 読者になる

Shin x Blog

PHPをメインにWebシステムを開発してます。Webシステム開発チームの技術サポートも行っています。

Laravel セッターインジェクションによる DI

Laravel のサービスコンテナでは、DI の手法として、コンストラクタインジェクションとメソッドインジェクションをサポートしています。サービスコンテナの機能を応用することで、セッターインジェクションを利用できます。

f:id:shin1x1:20151211111507p:plain

このエントリは、Laravelリファレンス Advent Calendar 2015 の11日目です。

セッターインジェクション

DI する対象クラスが、以下の MessageDeliveryクラスです。このクラスは、Sender を必要としているので、setSender メソッドで与えます。この setSender メソッドで依存インスタンスを与えるのが、セッターインジェクションです。

サービスコンテナを利用することで、このクラスをコンテナで解決すると、自動で setSender メソッドが実行され、Sender を実装したインスタンスを与えることができます。

class MessageDelivery
{
    /**
     * @var  Sender
     */
    protected $sender;

    public function send($to, $message)
    {
        $this->sender->send($to, $message);
    }

    public function setSender(Sender $sender)
    {
        $this->sender = $sender;
    }
}

サービスコンテナによるセッターインジェクション

サービスコンテナでセッターインジェクションを行うには、extend メソッドを利用します。これは、サービスコンテナにて解決を行った直後に自動で呼ばれる処理を登録するメソッドです。

この処理では、引数に解決されたインスタンスとサービスコンテナのインスタンスが渡されます。そこで、解決されたインスタンスのセッターメソッドを呼ぶことで必要なインスタンスを与えます。

下記が、その例です。ここでは、MessageDelivery::class を解決した際に実行する処理をクロージャで指定しています。クロージャでは、setSender メソッドで、Sender インターフェイスを実装した MailSender クラスのインスタンスを渡しています。

app()->extend(MessageDelivery::class, function ($instance, $app) {
    $instance->setSender(app()->make(MailSender::class));
    return $instance;
});

$delivery = app()->make(MessageDeliverySetterInjection::class);
$delivery->send('to', 'message');

さいごに

サービスコンテナによるセッターインジェクションを見てみました。extend メソッドは、セッターインジェクションのためだけのものではないので、解決に付随した処理(初期化等)があれば活用すると良いでしょう。

DI やコンストラクタインジェクション、メソッドインジェクションについては、下記をどうぞ :)

Laravel リファレンス[Ver.5.1 LTS 対応] Web職人好みの新世代PHPフレームワーク

Laravel リファレンス[Ver.5.1 LTS 対応] Web職人好みの新世代PHPフレームワーク