Aloha,

=== Summary ===
This has been implemented as part of the view layer pull request already 
(https://github.com/fabpot/symfony/pull/200), but even without the view layer I 
would advocate for the addition of a second method to do redirects, so that in 
the end there is one method which redirects to any URL and one that does 
"redirects" to the same application.

The goal is to require less code, less required dependencies to inject for the 
common use case. Also the ability to "optimize" the redirect to a forward in 
certain cases with little overhead.

=== Proposed Change ===
Currently when doing a redirect to the application itself something like the 
following is needed. When extending from the base Controller class (which is 
not a best practice) the code would look like this
$this->redirect($this->generateUrl('doctrine_user_user_list'));

Without extending from the base Controller the code would look like this and 
this is the base line used for the rest of this proposal:
$this->response->setRedirect($this->router->generateUrl('doctrine_user_user_list'));

With this proposal there would instead be two methods. For now I will refer to 
them as setRedirectX (for the current setRedirect, which accepts as url + code) 
and setRedirectY (for a method accepting a route + param + code). The final 
method names are open for discussion, but are a bike shedding issue:
$this->response->setRedirectX($this->router->generateUrl('doctrine_user_user_list'));
$this->response->setRedirectY('doctrine_user_user_list');

=== Details ===
Let's imagine a registration workflow implemented by come controller:
1) user clicks on a register button: registration form is displayed
2) user submits the form: user is stored and a page explaining further steps is 
displayed

Now when using a browser in step 2 we actually want to split up things in 2 
steps, because we want to prevent annoying warnings and double submissions if 
the user refreshes. We also want to provide a bookmark-able url:
2a) user submits the form: user is stored and a url to redirect to is returned
2b) browser redirects to the returned url: a page explaining further steps is 
displayed

Now when using AJAX to display the form and the explanations in an overlay we 
do not necessarily need this 2a) and 2b), we could do 2) as originally 
intended. We would thereby safe another round trip. Of course we might still 
choose to do 2a) and 2b) because we prefer to be explicit.

Now trying to implement the above inside a Controller atm requires logic to 
detect the actual output format to decide if to use a redirect() or a 
forward(). We could alternatively also simply extend the default Response class 
to:
- check if the Request _format isn't HTML
- check if the url passed to setRedirect() has the same domain as the current 
request
- check if the router can match the path of the passed url

If any of the checks fail we redirect happens as usual and if all checks pass 
we forward to the controller with the parsed parameters from the route that was 
matched.

However there would be no way for a developer to express if he wants to have 
the redirect automatically switched to a forward when the target format is not 
HTML. So a developer could only either stay with the logic as is, aka always 
return a target url when a redirect is done, or always convert a redirect to a 
forward in the non HTML case making this entire approach essentially not 
feasible.

By splitting the method in two, we can make the semantics explicit. Furthermore 
we do not have to first generate and then parse the URL, which should improve 
performance. Finally since the controller would not be responsible anymore for 
generating the url in the case when we do want the redirect to be convert-able 
into a forward, the code in that case would be shorter and wouldn't require a 
dependency on the router anymore. Since most redirects in applications actually 
point back to the application, this would simplify the code in the most common 
use case.

So the following:
// always return the redirect URL
$this->response->setRedirect($this->router->generateUrl('doctrine_user_user_list'));
$this->response->setRedirect('http://foo.com');

Could then be written as follows:
// always return the redirect URL
$this->response->setRedirectX($this->router->generateUrl('doctrine_user_user_list'));
$this->response->setRedirectX('http://foo.com');
// optionally forward to the route when the request _format isnt HTML
$this->response->setRedirectY('doctrine_user_user_list');

Choosing if to convert a redirect to a forward or not would then be easily 
implementable inside the Response (or View layer for that matter). The default 
behavior could also be up to debate or could be made configurable.

The way its implemented inside the view layer pull request is as follows:
$this->view->setRedirect() with format = 'html' -> redirect
$this->view->setRedirect() with format != 'html' -> forward
$this->view->setExternalRedirect() with format = 'html' -> redirect
$this->view->setExternalRedirect() with format != 'html' -> return url

Of course there is also still the possibility to do an explicit forward() just 
like before, however for that case there is no different between _format = 
'html' and _format != 'html' and therefore it does not concern this RFC.

regards,
Lukas Kahwe Smith
[email protected]



-- 
If you want to report a vulnerability issue on symfony, please send it to 
security at symfony-project.com

You received this message because you are subscribed to the Google
Groups "symfony developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/symfony-devs?hl=en

Reply via email to