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