Laravel/Lumen 拡張に欠かせないManagerクラスとは何か

Posted: 2015-05-11 21:09 |  laravel 
Laravel/Lumen使ってますか?
両フレームワークを使いこなす上で知っておかないと使いこなせないポイントの一つであろう
Managerクラスがあるのをご存知でしょうか?
これはIlluminateのSupportコンポーネントに含まれるもので、
Illuminate\Support\Managerクラスがそれです。

フレームワークの内部では、Cache、Session、Authで主に使われてます。
DatabaseもManagerクラスがありますが、Databaseはまたちょっと違うものです。

フレームワークを使っていて、認証クラスがなんか使いづらいなぁ。。
Sessionをdbとかmemcachedじゃなくて他のやつにしたいんだよ!
よくわからないから自分で作ってしまえ!

あれ、Laravelのクラスみたいに便利に動いてくれない・・
Authのファンクション使いたいけどこれのせいで使えない、全部作ってしまえ!

誰もが一度経験したことがあるでしょう。
そんなことをしなくてもよくしてくれるのがこのManagerクラスで、
このクラスとサービスコンテナ、サービスプロバイダを理解していないうちは
Laravelを使いこなしたぜ!という域にはまだ遠いです。
徐々に学んでいきましょう。

ではこいつは何者なんだ

このクラスはGoFのデザインパターンでいうファクトリパターンを簡単に利用するためのもので、
サービスコンテナやサービスプロバイダよりもはるかに簡単です。
Hogeなどの文字だけを返す簡単な仕組みを作ってみましょう。
namespace App\String;

use Illuminate\Support\Manager;

class StringManager extends Manager
{

    protected $driver = "hoge";

    /**
     * Get the default driver name.
     *
     * @return string
     */
    public function getDefaultDriver()
    {
        return $this->driver;
    }

}

StringManagerというクラスを作ります。
Managerクラスは抽象クラスで、継承時には必ずデフォルトのドライバを返すメソッドを実装します。
とりあえず$driver変数を`hoge`としました。
これをLaravelやLumenのクラスで自由に使うためには、サービスプロバイダを利用します。
なぜならば、ManagerクラスのコンストラクタではApplicationクラスを必要としているからですね。
このApplicationクラスはコンテナを拡張したもので、
StringManagerクラスでインスタンス生成されたクラスはコンテナの中身を自由に取り出すことができます。
サービスプロバイダへの登録は次のような感じです。
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\String\StringManager;

class AppServiceProvider extends ServiceProvider
{

    protected $defer = true;

    /**
     * @return void
     */
    public function register()
    {
        $this->app->bindShared("App\String\StringManager", function($app) {
            return new StringManager($app);
        });
    }
}
ただの文字を返却するクラスなのでdeferで利用するときまで何もしないように、
コンテナへの登録は、第一引数は文字列でなんでも良いんですが、
タイプヒンティングで利用するので、呼ばれた時にコンテナのインスタンスを引数に渡して生成するようにします。
これでフレームワーク内のどのクラスからでも利用できます
namespace App\Http\Controllers;

use Laravel\Lumen\Routing\Controller as BaseController;
use App\String\StringManager;

class Controller extends BaseController
{

    /**
     * @param StringManager $string
     */
    public function index(StringManager $string)
    {
        dd($string);
    }
}
StringManagerオブジェクトが取得できるはずです。
StringManagerクラスに戻りましょう。
次にhogeという文字列を返すようにするにはそれ用のクラスとマネージャクラスが指定された通りに
動的にインスタンスを生成できるようにしてあげます。
このクラスを継承するとdriverメソッドが利用できるようになり、
内部でcreateDriverメソッドを実行します。
このメソッドはクラス内のcreate'.'頭大文字のなんとか'.'Driver'メソッドを探して実行するわけです。
頭大文字はucfirstで勝手にやってくれるので意識しなくていいです。
つまり、今は$driver = 'hoge'のドライバがデフォルトになっているので、
createHogeDriverというメソッドを作ってあげればいいだけです。
StringManagerクラスに下記のメソッドを追加します。
 
    protected function createHogeDriver()
    {
        return "hoge";
    }
あとはさきほどのタイプヒンティングしたところを利用してこうします。
    public function index(StringManager $string)
    {
        dd($string->driver());
    }
driverメソッドに引数を与えずに利用するとデフォルトのドライバを使いますので、
createHogeDriverが呼ばれて文字列hogeがかえります。
では他の文字列も返してみましょう。
namespace App\String;

use Illuminate\Support\Manager;

class StringManager extends Manager
{

    protected $driver = "hoge";

    public function getDefaultDriver()
    {
        return $this->driver;
    }

    protected function createHogeDriver()
    {
        return "hoge";
    }

    protected function createFugaDriver()
    {
        return "fuga";
    }

    protected function createPiyoDriver()
    {
        return "piyo";
    }
}
これをdriverを利用してやるとこうなります。
    /**
     * @param StringManager $string
     */
    public function index(StringManager $string)
    {
        dd($string->driver(), $string->driver('fuga'), $string->driver('piyo'));

    }
hoge, fuga, piyoが出力されます。
要はこれだけです。
今は文字列ですが、同じようにしてdriverによって生成するインスタンスを変更できればいいわけですから、
Laravelのコアのソースコードを読めばドライバークラスの中身は同じような実装になってるはずです。
これを利用して拡張をしまくってみましょう!

サービスコンテナが難しいという方は、Laravelエキサパート養成読本に載っていますよ!
 

about ytake

執筆に参加しています


Laravel お役立ち情報

share



このエントリーをはてなブックマークに追加

Categories

laravel 45

DTM 0

music 0

PHP全般 31

0

JAPAN 1

WORLD 1

javascript 4

RDBMS 1

NoSQL 1

NewSQL 1

Recent Posts

Ad

comments powered by Disqus

GitHub

Social Links

Author


クリエイティブ・コモンズ・ライセンス
Yuuki Takezawa 作『Ytake Blog』はクリエイティブ・コモンズ 表示 - 非営利 4.0 国際 ライセンス で提供されています。

© ytake/comnect All Rights Reserved. 2014