Symfony2/SilexのControllerResolverを読む2
ところで、Silex\ControllerResolverにはこんなコードがあるんですがこれは何をやってるんでしょうねえ。
protected function doGetArguments(Request $request, $controller, array $parameters) { foreach ($parameters as $param) { if ($param->getClass() && $param->getClass()->isInstance($this->app)) { $request->attributes->set($param->getName(), $this->app); break; } } return parent::doGetArguments($request, $controller, $parameters); }
引数の$requestは当然リクエスト、$controllerは通常Silexでは無名関数、$parametersはReflectionFunction#getParameters()の戻り値で、ReflectionParameterの配列です。
http://jp2.php.net/manual/ja/reflectionfunctionabstract.getparameters.php
$param->getClass()->isInstance($this->app)
の部分ですが、ReflectionParameter#getClass()はReflectionClassのインスタンスを返すので、ReflectionClass#isInstance()が呼ばれています。これはこう書き換えることができます。
is_a($this->app, $param->getClass()->getName())
つまり、コントローラの仮引数がApplicationクラスであれば、$request->attributesにセットしている。で、最後にparent::doGetArguments()を呼び出しているということはもしかして、、、
コントローラの仮引数に"Application $app"って書いておけば勝手に渡ってくるってこと!?
つまり実は前回のコードはこれでいいってことか。
<?php require_once __DIR__.'/../vendor/.composer/autoload.php'; use Silex\Application; class LeapYearController { function indexAction(Application $app, $year) { //... } } $app = new Application(); $app->get('/is_leap_year/{year}', 'LeapYearController::indexAction'); return $app;
あーこれなら書いてみる気になりますね。よくできてるなーって関心しかけたけどいやいやいやいやちょっと待って。ってことは
$app->get('/hello/{name}', function($name) use($app) { return 'Hello '.$app->escape($name); });
じゃなくて
$app->get('/hello/{name}', function(Application $app, $name) { return 'Hello '.$app->escape($name); });
でも良かったってことじゃん!!
まだ続くかも。