$ 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?

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
}