[英]How does Symfony2 passes the parameter of a URI to the controller Action method?
我已经开始学习Symfony2。 我遇到一个疑问:如果我有这条路线:
# app/config/routing.yml
hello:
path: /hello/{name}
defaults: { _controller: AcmeHelloBundle:Hello:index }
而这个控制器:
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($name)
{
return new Response('<html><body>Ciao '.$name.'!</body></html>');
}
}
在内部Symfony2(在app / bootstrap.php.cache内部)调用PHP内置函数user_func_array()。
$arguments = $this->resolver->getArguments($request, $controller);
$response = call_user_func_array($controller, $arguments);
调用getArguments()方法将返回一个参数数组,以传递给action方法。 但是,如果控制器是:
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($n)
{
return new Response('<html><body>Ciao '.$n.'!</body></html>');
}
}
Symfony会抱怨RuntimeException,因为未设置参数$ n。
我的问题是:Symfony如何控制此行为,我的意思是,如果路由具有{name}参数,为什么控制器必须具有带有$ name参数的操作方法,并且该参数必须称为$ name?
在普通的PHP中,这会起作用:
$name = 'Alex';
function indexAction($n) {
echo $n;
}
$f = 'indexAction';
$arguments = array($name);
call_user_func_array($f, $arguments);
即使函数签名接受名为$ n而不是$ name的参数。
我希望这个问题是可以理解的,如果不能,请告诉我,我将进行编辑。
感谢您的关注!
这些都通过getArguments()
和doArguments()
在Controller Resolver HttpKernel / Controller / ControllerResolver.php中 getArguments()
。
为了更好地理解,您将在“ 获取控制器参数”中找到所需的内容。
编辑:回答评论。
Symfony是否在内部使用ReflectionParameter类来跟踪方法签名的参数并将它们与路由参数匹配?
是的,ControllerResolver使用:
如果$controller
是方法,则用ReflectionMethod跟踪方法签名的参数
如果$controller
是对象, $controller
ReflectionObject
如果$controller
是函数, $controller
ReflectionFunction
方法如下:
public function getArguments(Request $request, $controller)
{
if (is_array($controller)) {
$r = new \ReflectionMethod($controller[0], $controller[1]);
} elseif (is_object($controller) && !$controller instanceof \Closure) {
$r = new \ReflectionObject($controller);
$r = $r->getMethod('__invoke');
} else {
$r = new \ReflectionFunction($controller);
}
return $this->doGetArguments($request, $controller, $r->getParameters());
}
在您的示例中,您的操作上只有一个参数,因此对于我们来说很明显,需要从路径中填充该参数。
为了扩展您的示例,如果您向路由添加了另一个参数,例如:
# app/config/routing.yml
hello:
path: /hello/{name}/{surname}
defaults: { _controller: AcmeHelloBundle:Hello:index }
并将您的控制器更改为:
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($s, $n)
{
return new Response('<html><body>Ciao '.$n.' '.$s.'!</body></html>');
}
}
Symfony不知道用哪个路由参数填充哪个变量$s
或$n
。
如果您更改操作:
public function indexAction($surname, $name)
{
return new Response('<html><body>Ciao '.$name.' '.$surname.'!</body></html>');
}
现在,Symfony可以查看您的参数名称并将其映射到route参数。 这也意味着您可以以任意顺序使用indexAction
参数,只要它们的名称与route参数匹配即可。 我相信Symfony内部使用了Reflection API来解决所有这些问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.