In order to depend on using the Request object to determine caching, we need to ensure that everything uses it, rather than raw PHP variables for $_SERVER, $_REQUEST, $_GET, $_POST.
Conversion Guide
Remaining tasks: One last patch to remove all last $_GET, $_POST, $_COOKIE, $_REQUEST references. (Ignore $_SESSION for now, as it's being addressed elsewhere.)
Here are the methods on the Request object that map to PHP variables.
- $request->query The GET parameters
- $request->request The POST parameters
- $request->attributes The request attributes (parameters parsed from the PATH_INFO, ...)
- $request->cookies The COOKIE parameters
- $request->files The FILES parameters
- $request->server The SERVER parameters
See the Symfony documentation for an overview or a full list of convenience methods
- http://symfony.com/doc/current/components/http_foundation/introduction.html
- http://api.symfony.com/2.2/Symfony/Component/HttpFoundation/Request.html
To get the request object:
- If it is a route controller method, you can add a Request parameter as the last param in the method signature, and it will magically be passed in
- If you are in a new PSR-0, namespaced class, use
\Drupal::request()
(with a leading backslash) - If you are in old-skool functional land (e.g. includes) use
Drupal::request()
(without a leading backslash)
Sub-issues
..
Comment | File | Size | Author |
---|---|---|---|
#65 | 1998638.65.patch | 71.35 KB | alexpott |
#65 | interdiff.txt | 3.95 KB | alexpott |
#44 | globals-1998638.patch | 69.36 KB | dawehner |
#44 | interdiff.txt | 654 bytes | dawehner |
#42 | interdiff.txt | 1.65 KB | dawehner |
Comments
Comment #1
cosmicdreams CreditAttribution: cosmicdreams commentedHere's an example of what Kim's talking about. This converts common.inc's use of $_SERVER variables. I just want to see if this blows anything up.
Comment #2
cosmicdreams CreditAttribution: cosmicdreams commentedgo testbot.
Comment #2.0
kim.pepperAdded conversion guide
Comment #3
cosmicdreams CreditAttribution: cosmicdreams commentedThis patch converts all $_SERVER['REQUEST_METHOD']
Comment #3.0
cosmicdreams CreditAttribution: cosmicdreams commentedAdded getMethod() note
Comment #3.1
kim.pepperAdded link to symfony docs.
Comment #4
Damien Tournoud CreditAttribution: Damien Tournoud commentedAlternatively, we could decide to do something like this.
There is nothing wrong in using those globals, as long as we enforce that only one request is active at the same time, which is already true because we have
Drupal::request()
.Comment #4.0
Damien Tournoud CreditAttribution: Damien Tournoud commentedAdded link to request api page
Comment #4.1
kim.pepperAdded more files
Comment #6
Damien Tournoud CreditAttribution: Damien Tournoud commentedAbout #3: you need to use
$request->getMethod()
here. Reading from->server
directly is almost never the right thing to do.Comment #7
cosmicdreams CreditAttribution: cosmicdreams commented@Damien: Yea, Kim pointed that out to me after I did it. This seems like a great issue to spread out during code sprints.
Comment #8
kmcculloch CreditAttribution: kmcculloch commentedI am working on some of the subissues here at DrupalCon. It's easy to get $_SERVER, $_GET and $_POST from the Symfony Request object, but there does not seem to be an equivalent for $_REQUEST. Am I missing it? If it doesn't exist, what should I do: roll a $_REQUEST by hand by merging get, post and cookie, or try to figure out whether it's the get or the post that contains the id that would otherwise be passed into $_REQUEST?
Comment #9
Crell CreditAttribution: Crell commented$_REQUEST is an unreliable value anyway. Its data may change depending on server configuration. It shouldn't be used. You always care about whether data is coming in from query parameters or the request body (GET vs POST), and it's a bug in PHP that they let you merge them at all.
Comment #10
kmcculloch CreditAttribution: kmcculloch commentedI can't decide the best solution here. In the interest of moving forward, I'm going to avoid tampering with the $_REQUEST variables.
That said, based on my research, I see two general approaches. (I'm assuming that we don't need cookie variables, but I'm not sure if that's a safe assumption.)
The first is to merge the $query (i.e. GET) and $request (i.e. POST) objects:
$request = array_merge(\Drupal::request()->request->all(), \Drupal::request()->query->all());
$foo = $request['foo'];
The second is to check the request method and fetch an array conditionally:
if (\Drupal::request()->isMethod('GET')) {
$request = \Drupal::request()->query->all();
} else {
$request = \Drupal::request()->request->all();
}
$foo = $request['foo'];
The main problem I don't know how to address is order of precedence when $_GET and $_POST both contain the same array key. In a given PHP environment, the order of $_REQUEST depends on the variables_order configuration directive. The default value of this is 'GPCS' (at least, that's what came out of the box with my PHP), meaning $_GET comes before $_POST. But it could be changed. Then again, Drupal currently calls $_REQUEST without checking precedence (as far as I can tell), so this may be a non-issue.
Comment #11
kmcculloch CreditAttribution: kmcculloch commentedJust spoke to Kim. (Had no idea he was here in the room with us!) His recommendation is to use \Drupal::request()->get(), which pulls (in order) from GET, PATH, POST. This is slower than calling directly to GET or POST, so it's better to use those if you can figure out the context.
Comment #11.0
kmcculloch CreditAttribution: kmcculloch commentedAdded subissues
Comment #11.1
kim.pepperAdded more sub-tasks
Comment #11.2
kim.pepperAdded more links
Comment #11.3
kim.peppermore links
Comment #11.4
kim.pepperMore links
Comment #11.5
kim.pepperMore links
Comment #11.6
kim.peppertypo
Comment #12
Crell CreditAttribution: Crell commentedI still hold that anywhere we're using $_REQUEST now is a pre-existing bug. Whether we fix that here or later is a debatable point. :-)
Comment #13
kmcculloch CreditAttribution: kmcculloch commentedI'm inclined to agree with you, Crell. I went through and patched all of the core/includes files yesterday, and the only place I found $_REQUEST was in batch.inc:
These lines all occur within a function called _batch_page(), which is sprinkled throughout core:
I will return to the core/includes sub-issue later this week and study the context of _batch_page() to see if I can use a direct reference to the POST or GET data.
Comment #13.0
kmcculloch CreditAttribution: kmcculloch commentedRemoved files as they are now in the issues.
Comment #13.1
kim.pepperAdded more info about the request
Comment #14
Crell CreditAttribution: Crell commentedWait, what? This doesn't make any sense to me at all...
Comment #15
star-szrSince this is a meta, setting to active. Patching should be happening in the sub-issues.
Comment #15.0
star-szr.
Comment #16
Crell CreditAttribution: Crell commentedTagging
Comment #16.0
Crell CreditAttribution: Crell commentedRefreshing links
Comment #16.1
kim.pepperRefreshing statuses
Comment #16.2
kim.pepperUpdating status
Comment #17
webchickI committed the final two issues in the issue summary:
#1999388: Use Symfony Request for language module
#1999430: Use Symfony Request for simpletest module
However, it looks like we've managed to re-introduce some in the meantime. In addition to $_SESSION being used everywhere, there are stragglers in core/includes/ajax.inc, core/includes/bootstrap.inc, core/includes/install.core.inc, among others.
Comment #17.0
webchickRemove OpenID as it is no longer a core module.
Comment #18
cosmicdreams CreditAttribution: cosmicdreams commented$_SESSION is to be handled after we complete #1858196: [meta] Leverage Symfony Session components and is not apart of this issue.
Comment #19
Crell CreditAttribution: Crell commentedRefocusing the issue to finish this off.
Comment #20
damiankloip CreditAttribution: damiankloip commentedOk, so here is an initial attempt to 'finish it off', and one question:
Shall we do something with the 'lazy_session' global in this patch?
Comment #22
damiankloip CreditAttribution: damiankloip commentedLet's try this.
Comment #23
damiankloip CreditAttribution: damiankloip commentedF%&^
Comment #24
dawehneryeah 80 chars!
So you kind of jump from using !empty and ->has() all over the place. is there some logic behind that?
I wonder whether it is a good idea to break the session patch, which will change all the things anyway.
Note: this cannot work, as () is missing.
Can we keep somehow $request->request so it is more clear where the ajax page state was set?
For D9 we could maybe think about using a parameter bag instead of an array here, so it is a bit better to use.
Is it just me that removing "$_" in comments makes things harder to understand? Maybe we should just not hide that to the people, given that this is valuable information.
Just wondering whether you have tested this change.
Comment #26
Crell CreditAttribution: Crell commentedCan be replaced with http://api.symfony.com/2.3/Symfony/Component/HttpFoundation/Request.html...
Can be replaced with:
http://api.symfony.com/2.3/Symfony/Component/HttpFoundation/Request.html...
f.e. means "for example". i.e translates to "that is". Changing from f.e. to i.e. means that the string to parse is always the destination.
If you don't like f.e., then e.g. would be the alternative. Or, simply remove that clause from the sentence as it is rather pointless.
I think you need "for t() and $request to work", otherwise "request" seems like a verb, not a noun. And instead of "for", try "so that", which is more precise in this case.
Why do we set the cookie on the $request here....
But use setcookie() here?
Drupal::request(); lowercase method name.
That said, I don't know if we should be directly referring to the \Drupal class in all of these comments. Shouldn't it be something more like "the request", or...? (This applies in many places.)
I think your shift key is on strike. :-)
Yay!
Comment #27
damiankloip CreditAttribution: damiankloip commentedOK, thanks for the reviews. Most of the feedback addressed in this patch, I hope this should fix alot of the fails too.
I have not made the docs changes yet.
Comment #30
damiankloip CreditAttribution: damiankloip commentedFixing..
Comment #31
damiankloip CreditAttribution: damiankloip commentedLet's see how this gets on.
Comment #33
damiankloip CreditAttribution: damiankloip commentedLet's start with a reroll.
Comment #35
damiankloip CreditAttribution: damiankloip commented33: 1998638-33.patch queued for re-testing.
Comment #37
kim.pepperRe-roll
Comment #39
kim.pepperThis fixes the Form Storage tests, but not the AccessDenied test.
Comment #41
larowlanThis fixes the exceptions not the access denied, dawehner has fix for them
Comment #42
dawehnerI was to optimistic, though here is a analyze, for the access denied one
We might have to also provide an alternative implementation of the exception listener which also copies over the request type (post vs. get) and potentially passes along all the query attributes / post attributes.
@see ExceptionListener::64/65
@see ExceptionController::94
Comment #44
dawehnerLet's revert that little change in form.inc and fix it properly in #2147153: Replace the last instance of $_GET/$_POST; Create a special exception listener / exception controller which allows to use POST requests as this involves way more places than you would expect.
Comment #45
larowlan+1 rtbc
Comment #46
Crell CreditAttribution: Crell commentedWell then mark it as such. :-)
Comment #47
Ashleigh Thevenet CreditAttribution: Ashleigh Thevenet commentedSorry, updated the wrong issue - reverting
Comment #48
Ashleigh Thevenet CreditAttribution: Ashleigh Thevenet commentedComment #49
damiankloip CreditAttribution: damiankloip commentedThis looks good to me too. Thanks all for finishing this off, haven't had too much time recently..
Comment #50
webchickGreat work, folks! I feel cleaner reading Drupal 8 code already. :)
Committed and pushed to 8.x. Thanks!
Comment #51
webchickActually, since this marks the end of superglobals other than $_SESSION (which is coming later), we should issue a change notice for this (with before/after code), so people don't introduce them in future patches.
Comment #52
kim.pepperSuggested change notice:
PHP Super-globals replaced with Symfony Request object
In Drupal 7, you would access GET, POST, SERVER and COOKIE variables using the PHP super-globals $_GET, $_POST, $_SERVER and $_COOKIE.
Drupal 7:
In Drupal 8, you need to use the Symfony Request object.
Drupal 8:
More information on the Request object is available on the Symfony2 documentation pages. http://api.symfony.com/2.2/Symfony/Component/HttpFoundation/Request.html
Comment #53
jibranIt seems good to me. Please create a change notice for this and use php tag instead of code.
Comment #54
kim.pepperChange notice posted https://drupal.org/node/2150267
Comment #55
jibranThanks for the change notice.
Comment #56
alexpottThis has broken drush site-install and has not actually delivered on what the title promises "Replace all remaining superglobals...". For example, $_SERVER is still used in mail.inc, conf_path(), run-tests.sh
Either we should roll this back or we go forward with #2150279: Inconsistent use of request object in drupal_override_server_variables() and conf_path()
Comment #57
webchickI would be fine rolling this back, since it's only a "normal" task, except that it no longer cleanly rolls back. :(
So the race is on, to either provide a rollbackable patch here and fix the rest of the superglobals here, or to get #2150279: Inconsistent use of request object in drupal_override_server_variables() and conf_path() RTBC.
Comment #58
webchickOh, nevermind. That conflict is because confirm_form() no longer exists, so is irrelevant. Very well!
Rolled back until this issue actually does what it says on the tin. :P
Also, this implies we need some kind of tests that could've caught this. Not sure exactly how that works.
Comment #59
Mile23+1bn.
Eagerly awaiting #68387164: Refactor \Drupal Away.
Comment #60
damiankloip CreditAttribution: damiankloip commentedWhy are we reverting the whole patch? That seems mad to me. So now we need to worry about keeping the ~70k patch applied, rather than just a small follow up. Let's make more work for ourselves.
Also, when do we revert stuff because it breaks drush? If I checkout before the revert, I can install drupal (using drush si) fine.
What is meant to be tested here?
Comment #61
webchickI reverted the entire patch because normal tasks are not allowed to introduce critical bugs. If there's a subset of this patch I can commit that does not break drush si, let me know.
Comment #62
webchickAnd as far as testing, I'm not sure. Hopefully alexpott can provide some guidance, as he understands much better than I what broke. :)
Comment #63
damiankloip CreditAttribution: damiankloip commentedI'm not sure how drush si broke, hopefully alexpott can enlighten us on that. Usually it is drush that should catch up with core... So not sure where the critical bug is here?!
Comment #64
dawehnerWe also did not blocked the module disable patch to be applied due to the same reason.
So I applied the patch, ran my script which uses
drush si
and it still worked (twice), so what about renaming the titlefor now to be more honest?
All of the $_SERVER variables are probably hard to fix as it is code running really early in the installer.
Comment #65
alexpottPatch attached merges and improves fix from #2150279: Inconsistent use of request object in drupal_override_server_variables() and conf_path() and includes @Dave Reid's great idea on how to fix the warnings from mail.inc
drush site-install works for me with this patch.
Comment #66
dawehnerdrush si
still works for me.Comment #67
webchickAwesome! Thanks for the fast turnaround on this, alexpott!
Re-committed and pushed to 8.x. Thanks!
Comment #68
damiankloip CreditAttribution: damiankloip commentedWoop! Thanks all, that is some efficient resolution work.
Comment #70
alexpottWonder where #69 came from?
Drupal\system\Tests\Form\FormTest
passes locally.Comment #71
amateescu CreditAttribution: amateescu commentedIt was a memory issue on the testbot: