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.
If a contributed module stores its user related information NOT in users.data as user_schema() suggests, then that infromation is not added to the global $user object in sess_read() and this module should implement hook_init() to reload the current user.
function hook_init() {
global $user;
//user objects are not completly loaded when restored from session during bootstrap, so there are no extras.....
//$user->session exists only if the object comes from sess_read()
$user = ($user->uid && isset($user->session)) ? user_load($user->uid) : $user;
}
Is this by design or is this a bug or am I missing something?
Comment | File | Size | Author |
---|---|---|---|
#27 | drupal.user-load-full.27.patch | 1.14 KB | sun |
#19 | drupal.user-load-full.18.patch | 1.07 KB | sun |
#14 | full_user.diff | 687 bytes | moshe weitzman |
#12 | full_user.diff | 687 bytes | moshe weitzman |
Comments
Comment #1
Dave ReidIf you're not storing the data in $user->data, you would need to implement hook_user('load') to load in your own custom data into a user object.
Comment #2
Dave ReidComment #3
xmarket CreditAttribution: xmarket commented.. that is the reason I call user_load() in hook_init() not do some db_query().
function hook_init() {
global $user;
//user objects are not completly loaded when restored from session during bootstrap, so there are no extras.....
//$user->session exists only if the object comes from sess_read()
}
so my hook_user('load') is working.
Here is the sess_read() function:
and here is a snippet from user_load:
and here is the snippet from user_schema, which says, do not use users.data:
'data' => array(
'type' => 'text',
'not null' => FALSE,
'size' => 'big',
'description' => 'A serialized array of name value pairs that are related to the user. Any form values posted during user edit are stored and are loaded into the $user object during user_load().
Use of this field is discouraged and it will likely disappear in a future version of Drupal.
',),
???
Comment #4
xmarket CreditAttribution: xmarket commentedIf that is acceptable, that hook_boot() implementors can access only the "core" user object, than a few lines to _drupal_bootstrap_full() can solve the problem:
Comment #5
xmarket CreditAttribution: xmarket commentedComment #6
ainigma32 CreditAttribution: ainigma32 commented@xmarket: Are you saying you want this to be added to Drupal core? Because if you are you should set the version to 7.x (new features are always first implemented in HEAD and then backported) and you would also have to set the category to feature request
Finally you would have to write a patch http://drupal.org/patch/create that implements your suggestion
Is that where you were going with this issue?
- Arie
Comment #7
ainigma32 CreditAttribution: ainigma32 commentedLooks like xmarket won't be posting any feedback so I'm setting this to fixed.
Feel free to reopen if you think that is wrong.
- Arie
Comment #9
subspaceeddy CreditAttribution: subspaceeddy commentedI have run into this problem. I guess the question is - is this an oversight or by design? I can't find sess_read in D7 so assume things are done differently there. Basically, the problem:
1. I have custom user data that is added to global $user through hook_user(load)
2. in hook_init, I need to check this custom data and then redirect the user to a particular page depending on what's there.
3. at the point hook_init is invoked, the global $user has been pulled from the session (through sess_read) and not through user_load, meaning my custom data is not there.
It's not a big problem to load the user using $user->uid at this point, once you know what's happening, but it just feels *wrong* - it took me a while to track the problem properly, assuming that global $user would have been loaded through user_load from the start.
On looking quickly at other modules to see what they do, og,module invokes hook_user(load) at og_init, which is what I ended up doing too.
Is there a reason the fix suggested in #4 can not be implemented?
These two issues may possibly be related: http://drupal.org/node/489478, http://drupal.org/node/490108
Comment #10
sunComing from moshe's suggestion in #638070: Router loaders causing a lot of database hits for access checks, I agree we should fully populate $user after full bootstrap.
There are two locations where this could happen:
1) At the end of http://api.drupal.org/api/function/_drupal_bootstrap_full/7 (before module_invoke_all())
2) At the beginning of http://api.drupal.org/api/function/user_init/7
I would prefer the latter, because that would mean that a module that wants to act before this happens can still use hook_init() by using a negative module weight, so it runs before user_init().
Comment #11
moshe weitzman CreditAttribution: moshe weitzman commentedCan you give a use case for why a module needs to act before this and can't use hook_boot?
Comment #12
moshe weitzman CreditAttribution: moshe weitzman commentedThis patch adds the user_load() at end of FULL bootstrap. It depends on #490108: user_load() should add session properties when loading the currently logged-in user.
Comment #13
sunTrailing white-space here.
"build [the] full"...?
Perhaps also mention that we are _entirely_ overriding/replacing the previously defined global $user. Whatever was contained, whatever was altered, will be gone.
This review is powered by Dreditor.
Comment #14
moshe weitzman CreditAttribution: moshe weitzman commentedMade changes suggested by sun
Comment #19
sunProper patch extracted from #490108: user_load() should add session properties when loading the currently logged-in user
Comment #21
moshe weitzman CreditAttribution: moshe weitzman commentedthanks for keeping this moving.
Comment #24
carlos8f CreditAttribution: carlos8f commentedI'm -1 on this patch:
In D6 this created all kinds of problems since user_load() wasn't statically cached. D7 caches it though, so multiple calls to user_load() in various hooks and callbacks add a very small performance hit to reference the static variable. I'm a proponent of lazy-loading and I see this as a good chance to use it, since we now have the static caching necessary.
Doing user_load() accounts for 5-8% of a page load, which is wasteful if we don't use the full $user. #638070: Router loaders causing a lot of database hits for access checks is intended on cutting that waste, and this patch would nullify that effort.
Comment #25
catchSame here, there's no critical bug caused by this, most people figure it out pretty quickly, and it's no longer the false optimization it was in D6. We just go to the point where you can do a full bootstrap without any database queries, and this would make that impossible, as well as the 4-6% hit on sites which turn out not to need it.
Comment #26
moshe weitzman CreditAttribution: moshe weitzman commentedIt is true that there is no critical core bug caused by this, and many people figure it out. Those are not reasons to block this. This fixes a Drupal WTF that traps many developers. Most eventually recover, but I think we should aim to not have the trap to begin with.
1. I think that on almost all substantial sites, the user object gets loaded for the current user. It is mostly in the vacuum of core where it appears that we can avoid this.
2. Sites watch performance close enough to care about are going to run with persistent entity caching and thus its a non-issue.
I think this is a case where we should choose correctness over performance.
Anyone up for a reroll? Its looking like we need some committer input soon.
Comment #27
sunI guess it doesn't really make sense for the anonymous user, because there's most likely not much to load. And I guess this is what makes others here a bit nervous about performance.
For authenticated users, it's very very likely that the full $user object of the current user will be loaded anyway.
So how about this compromise?
Comment #28
moshe weitzman CreditAttribution: moshe weitzman commentedWorks for me.
Comment #29
carlos8f CreditAttribution: carlos8f commentedI prefer sun's patch, but I'm still kind of skeptical. I don't think core should get in the habit of doing non-trivial processing unless the data is actually required. Whether or not core is a 'vacuum' in this case is unfounded, let's see an actual list of contrib modules that require a user_load($user->uid) on every request.
@moshe FYI, entity caching on users may not be possible in D7, see:
http://drupal.org/node/638070#comment-2390978
#665618: Add entity caching for users
Comment #30
catchYes, entity caching of users is a lot more tricky than other entities, and while I have working code for everything else either in patches or contrib, I've only had major test breakage for users so far. So relying on that isn't a safe bet as this point.
Doing this in any full bootstrap is also going to affect things like autocomplete etc, which are quite likely to run without a user_load() unless you have another module doing it in hook_boot() or hook_init(), so I really don't think it's a false optimization, and would also like to see a list of contrib modules which force it.
Comment #31
moshe weitzman CreditAttribution: moshe weitzman commentedOK, I'm willing to let this one go. Lets revisit it when entity cache is available for users (D8, I hope). If someone else to move it back to 7, feel free to don your battle gear and do so.
Comment #32
catchIf we can get user caching in core, that's likely to be the place where it's actually a decent gain even with database caching out of the box, so hopefully (early) D8 yeah.
Comment #33
Damien Tournoud CreditAttribution: Damien Tournoud commentedOnly feature requests and tasks can be assigned to D8 for now, because the Drupal 8 tree is not opened yet.
Fortunately, this is more a feature request.
Comment #34
Dave ReidWe can at least easily fix this for the [current-user] token: #967330: The [current-user:?] token should provide the actual loaded user.
Comment #35
catchfwiw entitycache has had user support for a little while now, I haven't checked whether it can pass core tests yet but it's been running in production for months with no noticeable side effects. So I'd have much less of an issue with this for Drupal 8. Although entitycache is currently only used on 5 sites, so doing this without caching support in core still concerns me a bit.
Comment #36
bleen CreditAttribution: bleen commentedsubscribing
Comment #37
ohnobinki CreditAttribution: ohnobinki commented.
Comment #38
playahater CreditAttribution: playahater commented#12: full_user.diff queued for re-testing.
Comment #39
boombatower CreditAttribution: boombatower commentedSubscribe.
Ran into this with a field attached to the user that effected node access. When attempting to check the field in hook_node_access() $account did not contain it, but user_load($account->uid) did.
Comment #40
q0rban CreditAttribution: q0rban commentedI'm confused. How is this not a bug? If I call user_load(1234) and user 1234 is the currently logged in user, none of the fields are loaded. If user 1234 is NOT logged in, all fields ARE loaded.
Comment #41
q0rban CreditAttribution: q0rban commentedWhoops, sorry, I'm wrong. My dpm was one page load behind. So user_load did contain the fields and data, but global $user did not.
Comment #42
RobLoachTagging Dependency Injection since we could dynamically lazy-instantiate the User object with it. Should this wait until we actually have a class for it? #1361228: Make the user entity a classed object
Comment #43
sunI think we should ditch this proposal entirely and do the opposite:
#1549526: Change global $user into $session
Comment #44
fagopostponed http://drupal.org/node/1634280 on this
Comment #45
sunI guess it is safe to say by now that this won't happen.
As a stop-gap fix we may do #1549526: Change global $user into $session, but in reality, we want to replace the entire session handling (which would eliminate global $user entirely).
Comment #46
IRuslan CreditAttribution: IRuslan as a volunteer and at DrupalJedi commentedI just would like to re-roll patch from #27 to last drupal 7 version. Maybe will be useful for someone.