My I/O

インプットしたことをアウトプットするブログ

Laravel5.5 サービスプロバイダー

  • サービスプロバイダはアプリケーション設定の中心部
  • サービスプロバイダを利用し、初期起動処理(サービスコンテナの結合、イベントリスナ、フィルター、ルートなどの登録)する
  • config/app.phpファイルのproviders配列に記述されたサービスプロバイダが、ロードされる。
    • 実際に必要なときにのみロードされる「遅延」プロバイダがほとんど

register()はサービスコンテナの記事のときに使ったことがあるので、 boot()と遅延ロードの仕方を勉強。

boot()は他の全サービスプロバイダが登録し終えてから呼び出される

register()で登録した依存を、 boot()のタイプヒンティングで使ってみる。

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Contracts\TestContainer;

class MichikoTestServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot(TestContainer $container)
    {
        var_dump('boot() ' . $container->hoge());die;
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {

        $this->app->bind(
            'App\Contracts\TestContainer',
            'App\Test\MichikoContainer'
        );
    }
}

f:id:michikoxxx:20180221111712p:plain

できました!

先にregister()でサービスコンテナでTestContainerとMichikoContainerが結合されて、  boot()でTestContainerをタイプヒンティングしたので、MichikoContainer使えるようになってました。 でもこの例の使い方じゃ意味ないかな…。

デフォルトのサービスプロバイダでいうと、encrypterやcookieなどなどがboot()時には使えるようになっているので config/app.phpのprovidersをチェックしてみるとこれbootで使えるんじゃんとなるのかな、と。

遅延ロードにしたいなら protected $defer = true;provides() を用意する

プロバイダを作る上で、基本遅延ロードにする頭の片隅にあるとよさそうな気がする。 最初からロードしておきたいものばっかり作ることは少ないだろうし。 遅延ロードで困ったとなったら戻せばいいしね。

    protected $defer = true;

  …

    public function provides()
    {
        return [TestContainer::class];
    }

利用の場面を考える

例えば会員登録をして利用するWebアプリケーションの場合、 ユーザーモデル的な物が欲しいわけで、 シングルトンでサービスコンテナで依存投入かな?

そして会員ランクや、管理者ログインなどの場合で機能が違う場合は $this->app->when(..).needs(..).give(); とかで実装を振り分けられるかな?

ちょっともっといい例が出せればいいけれども...会員登録があるWebサービスを趣味で作るっていってもなんか目的が必要だし… 思ったことは以上です。