ルーティング周りを読んでいて気になった内部的なローディングのことを少し確認しておく。
laravelはたくさんのServiceProviderが提供するサービスを利用して動いている(?)
ServiceProviderをregisterすることで、色々なところから使える状態になる
https://github.com/laravel/framework/blob/4.2/src/Illuminate/Support/ServiceProvider.php#L44
以前読んだRoutingのServiceに加えて、Event, ExceptionはBaseServiceProviderとして特別扱いされていて、Applicationのコンストラクタで呼ばれてregisterされている
protected function registerBaseServiceProviders()
{
foreach (array('Event', 'Exception', 'Routing') as $name)
{
$this->{"register{$name}Provider"}();
}
}
それ以外はstart.phpから。
https://github.com/laravel/framework/blob/4.2/src/Illuminate/Foundation/start.php#L208L210
$providers = $config['providers']; $app->getProviderRepository()->load($app, $providers);
このProviderRepositoryがeagerに読み込むかlazyに読み込むかなど振り分けつつ、ここでServiceProviderたちをregisterしている
registerは何をすることなのか。
Routingの場合は$app['router']にRouteをセットすることだった。
AuthServiceProvider
public function register()
{
$this->app->bindShared('auth', function($app)
{
// Once the authentication service has actually been requested by the developer
// we will set a variable in the application indicating such. This helps us
// know that we need to set any queued cookies in the after event later.
$app['auth.loaded'] = true;
return new AuthManager($app);
});
}
CacheServiceProvider
public function register()
{
$this->app->bindShared('cache', function($app)
{
return new CacheManager($app);
});
$this->app->bindShared('cache.store', function($app)
{
return $app['cache']->driver();
});
$this->app->bindShared('memcached.connector', function()
{
return new MemcachedConnector;
});
$this->registerCommands();
}
CommandsServiceProvider
public function register()
{
$this->app->bindShared('command.session.database', function($app)
{
return new Console\SessionTableCommand($app['files']);
});
$this->commands('command.session.database');
}
これらを見ているとbindSharedを呼び出すのがメインっぽい
bindSharedのやっていることはこれだけで、bindを単にちょっとラップしてるだけ。offsetSetからもbindは呼ばれていて、ただその場合は第3引数が渡されないのでsharedがfalseになる。
public function bindShared($abstract, Closure $closure)
{
return $this->bind($abstract, $this->share($closure), true);
}
bindにClosureが渡されていない場合はgetClosureというのが呼ばれる
protected function getClosure($abstract, $concrete)
{
return function($c, $parameters = array()) use ($abstract, $concrete)
{
$method = ($abstract == $concrete) ? 'build' : 'make';
return $c->$method($concrete, $parameters);
};
}
結構Closureを多用している感あるなー。今回はclosureが渡されているので関係ないけど
aliasの設定とかゴニョゴニョしつつ
array(
'concrete' => Closure,
'shared' => bool
)
な形で$appからアクセスできるように追加している。これがregisterということかな。
sharedは何に使われているのかまだ見ていないけど、$appにブラケットでアクセスしようとすると、そのkeyでmake($key)が呼ばれて、concreteのclosureを使って作られたインスタンスを取得できるという感じ。