Php Symfony2如何将URI的参数传递给控制器操作方法?

Php Symfony2如何将URI的参数传递给控制器操作方法?,php,symfony,controller,action,Php,Symfony,Controller,Action,我已经开始学习Symfony2了。我遇到了一个疑问:如果我有这条路线: # app/config/routing.yml hello: path: /hello/{name} defaults: { _controller: AcmeHelloBundle:Hello:index } 该控制器: // src/Acme/HelloBundle/Controller/HelloController.php namespace Acme\HelloBundle\Cont

我已经开始学习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>');
    }
}
对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>');
    }
}
即使函数签名接受名为$n而不是$name的参数

我希望这个问题是可以理解的,如果没有,请告诉我,我会做一个编辑

谢谢你的关注

  • 该请求由Symfony前端控制器(例如app.php)处理
  • Symfony内核(即内核)要求路由器检查请求
  • 路由器将传入URL与特定路由匹配,并返回有关路由的信息,包括应执行的控制器
  • Symfony内核执行控制器,控制器最终返回一个响应对象
  • 该请求由Symfony前端控制器(例如app.php)处理
  • Symfony内核(即内核)要求路由器检查请求
  • 路由器将传入URL与特定路由匹配,并返回有关路由的信息,包括应执行的控制器
  • Symfony内核执行控制器,控制器最终返回一个响应对象

  • 在您的示例中,您的操作只有一个参数,因此我们很明显,它需要从路由填充

    若要扩展示例,请向管线添加另一个参数,例如:

    # 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可以查看参数名称并将它们映射到路由参数。这还意味着您可以按任何顺序使用
    索引
    参数,只要它们的名称与路由参数匹配。我相信Symfony在内部使用反射API来解决所有这些问题。

    在您的示例中,您的操作只有一个参数,因此我们很明显,它需要从路由填充

    若要扩展示例,请向管线添加另一个参数,例如:

    # 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可以查看参数名称并将它们映射到路由参数。这还意味着您可以按任何顺序使用
    索引
    参数,只要它们的名称与路由参数匹配。我相信Symfony在内部使用反射API来解决所有这些问题。

    这一切都是通过
    getArguments()
    &
    doArguments()
    在控制器解析器中完成的

    为了更好地理解,您将在中找到您需要的


    编辑:回答评论

    Symfony是否在内部使用ReflectionParameter类来跟踪方法签名的参数并将其与路由参数匹配

    是,ControllerResolver使用:

    • 如果
      $controller
      是方法,则跟踪方法签名的参数

    • 如果
      $controller
      是一个对象

    • 如果
      $controller
      是一个函数

    以下是如何:

     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());
        }
    

    这一切都是通过
    getArguments()
    doArguments()
    在控制器解析器中完成的

    为了更好地理解,您将在中找到您需要的


    编辑:回答评论

    Symfony是否在内部使用ReflectionParameter类来跟踪方法签名的参数并将其与路由参数匹配

    是,ControllerResolver使用:

    • 如果
      $controller
      是方法,则跟踪方法签名的参数

    • 如果
      $controller
      是一个对象

    • 如果
      $controller
      是一个函数

    以下是如何:

     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());
        }
    

    是的,我知道Symfony处理请求,但我不明白的是Symfony如何保证路由的参数与action Controller方法的参数完全对应,也就是说,如果我有这个路由
    path:/hello/{firstName}/{lastName}
    ,它与
    HelloController::indexAction($firstName,$lastName)
    匹配,symfony如何控制indexAction控制器方法所需的每个参数必须对应于路由的一个参数?为什么像
    HelloController::indexAction($first\u name,$last\u name)
    这样的方法会引发RuntimeException?是的。使用ReflectionClass?是的,它是@user3019105,请看我的回答是的,我知道Symfony处理请求,但我不明白的是Symfony如何保证路由的参数与action Controller方法的参数完全对应,即如果我有这个路由
    path:/hello/{firstName}/{lastName}
    哪个与
    HelloController::indexAction($firstName,$lastName)
    匹配,symfony如何控制indexAction控制器方法所需的每个参数必须与路由的参数相对应?为什么像
    HelloController::indexAction($first\u name,$last\u name)
    这样的方法会引发RuntimeException?是的。使用ReflectionClass?是的@user3019105,请参阅我的回答Symfone是否在内部使用该类来跟踪方法签名的参数并将其与路由参数匹配?感谢您的说明!对不起,我还有最后一个问题。因此,Symfony在每次请求时都会进行此控制(无论您是在dev还是prod环境中),对吗?Symfone是否在内部使用该类来跟踪方法签名的参数并将其与路由参数匹配?感谢您的说明!对不起,我还有最后一个问题。所以Symfony在每次请求时都会执行此控制(无论您是在dev环境还是prod环境中),对吗?