dongpao1905 2013-05-05 08:44
浏览 54

$ this-> forward丢失了用户的请求路由?

I want to redirect admins to /admin and members to /member when users are identified but get to the home page (/).

The controller looks like this :

public function indexAction()
{
    if ($this->get('security.context')->isGranted('ROLE_ADMIN'))
    {
        return new RedirectResponse($this->generateUrl('app_admin_homepage'));
    }
    else if ($this->get('security.context')->isGranted('ROLE_USER'))
    {
        return new RedirectResponse($this->generateUrl('app_member_homepage'));
    }
    return $this->forward('AppHomeBundle:Default:home');
}

If my users are logged in, it works well, no problem. But if they are not, my i18n switch makes me get a nice exception :

The merge filter only works with arrays or hashes in "AppHomeBundle:Default:home.html.twig".

Line that crashes :

{{ path(app.request.get('_route'), app.request.get('_route_params')|merge({'_locale': 'fr'})) }}

If I look at the app.request.get('_route_params'), it is empty, as well as app.request.get('_route').

Of course, I can solve my problem by replacing return $this->forward('AppHomeBundle:Default:home'); by return $this->homeAction();, but I don't get the point.

Are the internal requests overwritting the user request?

Note: I'm using Symfony version 2.2.1 - app/dev/debug

Edit

Looking at the Symfony's source code, when using forward, a subrequest is created and we are not in the same scope anymore.

/**
 * Forwards the request to another controller.
 *
 * @param string $controller The controller name (a string like BlogBundle:Post:index)
 * @param array  $path       An array of path parameters
 * @param array  $query      An array of query parameters
 *
 * @return Response A Response instance
 */
public function forward($controller, array $path = array(), array $query = array())
{
    $path['_controller'] = $controller;
    $subRequest = $this->container->get('request')->duplicate($query, null, $path);

    return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}

By looking at the Symfony2's scopes documentation, they tell about why request is a scope itself and how to deal with it. But they don't tell about why sub-requests are created when forwarding.

Some more googling put me on the event listeners, where I learnt that the subrequests can be handled (details). Ok, for the sub-request type, but this still does not explain why user request is just removed.

My question becomes :

Why user request is removed and not copied when forwarding?

  • 写回答

1条回答 默认 最新

  • duanpie2414 2013-05-06 15:48
    关注

    So, controller actions are separated part of logic. This functions doesn't know anything about each other. My answer is - single action handle kind of specific request (e.g. with specific uri prarams). From SF2 docs (http://symfony.com/doc/current/book/controller.html#requests-controller-response-lifecycle):

    2 The Router reads information from the request (e.g. the URI), finds a route that matches that information, and reads the _controller parameter from the route;

    3 The controller from the matched route is executed and the code inside the controller creates and returns a Response object;

    If your request is for path / and you wanna inside action (lets say indexAction()) handling this route, execute another controller action (e.g. fancyAction()) you should prepare fancyAction() for that. I mean about using (e.g.):

    public function fancyAction($name, $color)
    {
        // ... create and return a Response object
    }
    

    instead:

    public function fancyAction()
    {
        $name = $this->getRequest()->get('name');
        $color = $this->getRequest()->get('color');
        // ... create and return a Response object
    }
    

    Example from sf2 dosc:

    public function indexAction($name)
    {
        $response = $this->forward('AcmeHelloBundle:Hello:fancy', array(
            'name'  => $name,
            'color' => 'green',
        ));
    
        // ... further modify the response or return it directly
    
        return $response;
    }
    

    Please notice further modify the response.

    If you really need request object, you can try:

    public function indexAction()
    {
        // prepare $request for fancyAction
    
        $response = $this->forward('AcmeHelloBundle:Hello:fancy', array('request'  => $request));
    
        // ... further modify the response or return it directly
    
        return $response;
    }
    
    public function fancyAction(Request $request)
    {
        // use $request
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上