Laravel5のContainerクラスのメンバ変数に関して

スポンサーリンク

こんにちは。ファガイです。
本日は、Laravel5のContainerクラスに存在するメンバ変数に関して調べました。

resolved

すでに解決済みの依存関係情報を登録しています。Containerでmakeされるまではresolvedには情報は入りません。
基本的に、'binding名' => trueで入ります。

bindings

すでにコンテナにバインディングされているかの情報が入っています。
中身は’binding名’ => [‘concrete’ => ‘binding先'(, ‘shared’ => true)]

$this->app->bind('FooInterface', 'Bar');
→'FooInterface' => ['concreate' => Closure]

$this->app->singleton('FooInterface', 'Bar');
$this->app->bindShared('FooInterface', function($app) {
    return new Bar;
});
→'FooInterface' => ['concreate' => Closure, 'shared' => true]

instances

共有インスタンス化されている物が配列で入っています。
makeメソッドが呼ばれた際、そのbindingsのsharedがtrueだった場合や、instanceメソッドでインスタンスを登録する場合にこのinstancesに登録されます。
中身は、'binding名' => インスタンスそのもの です。

aliases

2015/05/06 内部仕様を勘違いしていたので修正しました。

別名を登録する際に使われています。主に使用されるのはコンストラクタインジェクション等を使えるようにするために使われてます。
中身は、'alias名' => 'binding名'です。
Applicationクラスの最後の方に、aliasの登録が存在するので見ると良いです。

extenders

bindingされている物に対して、makeされる際に追加で何か実行させたい等があるときにはこれが使われています。
extendメソッドでextendersに登録しています。
中身は'binding名' => [Closure,Closure・・・]です。

tags

タグに対応したbindingされている物が格納されています。
登録には、tagメソッド、取得にはtaggedメソッドを使います。また、taggedで返されるのは、tagに紐付いているbindingをmakeした物が配列で返されます。

タグ付け – サービスコンテナ 5.0.0 Laravel

buildStack

自身で読み解いていった結果、コンテキストバインディングを使用するときだけこのbuildStackが使われているようです。現状ではコンテキストバインディングにしか使われていないようなので、あまり気にしないほうがいいのと、そもそもメンバ変数でこれを持つべきなのかと微妙な感じです。
build→データを入れる→getDependencies→resolveClass→make→getConcrete→getContextualConcreteでデータを使用している→buildまで戻ってきたらデータをpopして出す

contextual

コンテキストバインディングの情報が入ります。
Containerクラスのwhenメソッドが呼ばれるとContextualBindingBuilderクラスがnewされ、最終的にgiveメソッドが呼ばれるとContainerクラスのaddContextualBindingメソッドを通じてこの配列に登録されます。

$this->contextual[whenメソッドの第1引数][needsメソッドの第1引数] = giveメソッドの第1引数

コンテキストに合わせた結合 – サービスコンテナ 5.0.0 Laravel

reboundCallbacks

resolve済みのbindingが再度インスタンスが登録(rebound)される際に呼ばれるコールバック関数がこの中に入ります。
追加する際には、rebindingメソッドを使います。
vendor/laravel/framework/src/Illuminate/Routing/RoutingServiceProvider などで実際に使われてます。

Resolving系

いきなり見出しをつけてしまいましたが、resolving関係はメンバ変数が複数存在し、実際登録する際のコールバックが一緒だったのでまとめています。

Resolving関係は、依存関係が解決された際(make)に毎回呼ばれます。(singleton等は基本的に最初の1回だけです。)
また、Resolvingはextenderよりも後に発火します。

コンテナイベント – サービスコンテナ 5.0.0 Laravel

make時に発火される順番

resolvingのイベントは複数指定が可能なので、発火される順番が存在します。以下となります。

  1. globalResolvingCallbacks
  2. resolvingCallbacks
  3. globalAfterResolvingCallbacks
  4. afterResolvingCallbacks

resolving登録時のコールバック

$callback(生成されたオブジェクト, Applicationコンテナ)

上記のように渡されます。

globalResolvingCallbacks

resolvingメソッド→resolvingCallbackメソッドで登録されます。クロージャの第1引数でクラス指定をしなければこちらに登録されます。
全ての依存関係が解決される際に毎回呼ばれます。

$this->app->resolving(function($object, $app)
{
    // どんなものでもmakeされれば実行されます
});

resolvingCallbacks

resolvingメソッドまたは、resolvingCallbackメソッドで登録されます。resolvingCallbackメソッドでは、クロージャの第1引数でクラス指定をするとこちらに登録されます。
依存解決の名前が第1引数で指定したものに対応した名前でないと、このコールバックは動作しません。

$this->app->resolving(function(FooBar $fooBar, $app)
{
    // FooBarでbindingされているまたは、FooBarクラスだったら実行されます
});

$this->app->resolving('FooBar', function($fooBar, $app)
{
    // これでも同じです
});

globalAfterResolvingCallbacks

afterResolvingメソッド→afterResolvingCallbackメソッドで登録されます。クロージャの第1引数でクラス指定をしなければこちらに登録されます。
その他情報はglobalAfterResolvingCallbacksと同じです。

afterResolvingCallbacks

afterResolvingメソッドまたは、afterResolvingCallbackメソッドで登録されます。afterResolvingCallbackメソッドでは、クロージャの第1引数でクラス指定をするとこちらに登録されます。
その他情報はresolvingCallbacksと同じです。

まとめ

まだまだ理解できてない曖昧な部分が有りますがある程度理解できて良かったです。
resolvingやextenderに関しては新鮮でしたー。

コメント

タイトルとURLをコピーしました