Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
In #1668866: Replace drupal_goto() with RedirectResponse we introduced the following pattern...
- drupal_goto("node/$node->nid");
+ return new RedirectResponse(url("node/$node->nid", array('absolute' => TRUE)));
This is issue will discuss if we can improve the pattern by removing the eminently forgetable array('absolute' => TRUE)
Proposed resolution
- Subclass RedirectResponse and check the passed url. if not external make it so
- Wrap the whole thing in a service and dont use RedirectResponse directly. Apply same logic as above
- Add a method to Url generator. Given that most callbacks that use redirection will be converted eventually to the new routing system, with url generator injected...instead of calling
generateFromPath
, callgenerateAbsolute
- Provide a Base class with a redirect() method that also takes care of the dependency on the url generator service. Something like #2018411: Figure out a nice DX when working with injected translation
Comments
Comment #1
catchI'd also like to see if we could remove the url() call so this ends up using the generator more or less directly - if we want to eventually be able to move routes around without updating path strings, this is a necessary step towards that.
Bumping to major because this needs to be resolved before code freeze if possible.
Comment #1.0
ParisLiakos CreditAttribution: ParisLiakos commentedAdded some potential resolutions
Comment #2
Crell CreditAttribution: Crell commented1) As long as we don't break any existing code I don't think it should be blocked by code freeze. Although I agree that sooner=better.
2) One issue with putting it on the generator is that there are two pathways there: By path fragment and by route name. An increasing percentage of the system is now route-name-based, which means we can/should be moving a lot of url() calls over to using route names rather than paths. Yes, using an injected generator.
3) Symfony fullstack has a ContainerAware Controller base class that has utility methods like ->redirect(), which handles that sort of thing. We don't have a base class and have made the decision to not make all controllers container aware. However, we're doing something with an optional base class for translation, most likely: #2018411: Figure out a nice DX when working with injected translation. Damnit, I want traits!
Comment #3
ParisLiakos CreditAttribution: ParisLiakos commentedi like that...because that would also handle the url generator dependency as well, double win:)
Comment #3.0
ParisLiakos CreditAttribution: ParisLiakos commentedturn ul to ol
Comment #4
Crell CreditAttribution: Crell commentedExcept for the next sentence in that paragraph. :-) Adding a base class now involves a not-small amount of change.
Comment #5
chx CreditAttribution: chx commentedAlso #185 in the parent talks about firing an event before the url is constructed so that $path and $options are not lost.
Comment #6
ParisLiakos CreditAttribution: ParisLiakos commentedTo clarify: I dont talk about a response event..I talk about an event (or it can be hook_alter, i am not sure what we do for newly introduced things like that) which will fire before the url is being passed to the Url generator, before the RedirectResponse is being created...but even with this, noone can guarantee that a response can fire only by a controller.
See eg the Goto action..
Comment #7
agentrickardSomething related (DX/UX wise) that is worth mentioning here.
With drupal_goto(), you could pair that call with drupal_set_message() to send a message regarding the redirect. The RedirectResponse class doesn't support that. It's a new request, and the information in drupal_set_message() seems to be destroyed.
Comment #8
Crell CreditAttribution: Crell commenteddrupal_set_message() hasn't really changed (yet). I think the issue in #7 is unrelated, in that we're still calling drupal_get_messages() when we shouldn't be, which is clearing out the session-stored messages. That's a straight up bug in its own right, but separate from the issue here.
Perhaps a redirect subclass, RouteRedirectResponse('some_route_name', $array_of_placeholders)? Then a response listener that pulls that data out, runs it through the generator, and then sets the redirect target on the response before passing it along. So modules would do something like:
And the rest gets taken care of by the listener.
Comment #9
dlu CreditAttribution: dlu commentedMoved to routing system per #2050763-16: Refine "base system" component (notes on refactoring of "base system" category here: https://docs.google.com/a/acquia.com/spreadsheet/ccc?key=0AusehVccVSq2dF...).
Comment #9.0
dlu CreditAttribution: dlu commentedAdd base class proposal
Comment #10
Crell CreditAttribution: Crell commentedNote that the new ControllerBase class has a redirect() method, so that's at least some use cases addressed.
Comment #11
tim.plunkettI'd like to think that between ControllerBase having $this->redirect(), and $form_state['redirect']/$form_state['redirect_response'] still working, that this is no longer major.
Comment #12
Crell CreditAttribution: Crell commentedSince you shouldn't be firing a redirect from anywhere else besides a controller or a form, I would say this is done per #11.