[wp-trac] [WordPress Trac] #58001: Lazy load user capabilities in WP_User object
WordPress Trac
noreply at wordpress.org
Fri Oct 10 17:44:59 UTC 2025
#58001: Lazy load user capabilities in WP_User object
----------------------------------+-------------------------------------
Reporter: spacedmonkey | Owner: flixos90
Type: enhancement | Status: reopened
Priority: normal | Milestone: 6.9
Component: Users | Version:
Severity: normal | Resolution:
Keywords: early needs-dev-note | Focuses: multisite, performance
----------------------------------+-------------------------------------
Comment (by bradshawtm):
> As for get_object_vars, this was considered, but it feels super edge
case
I'm not convinced this point is edge case given it came up twice shortly
after this change was merged. I suspect directly serializing a `WP_User`
object is fairly common practice. I just realized this also affects
`json_encode()`/`wp_json_encode()`, neither of which will export the
protected properties even if populated:
```
<?php
function test_json_encode() {
$user = new WP_User(1);
error_log(var_export( wp_json_encode( $user ), true)); // no roles
$user->roles;
error_log(var_export( wp_json_encode( $user ), true)); // no roles
}
add_action('wp_footer', 'test_json_encode');
```
----
> I used a magic setter, so this should work.
One can't directly modify the array elements of a protected property, and
I don't think there's a way for the magic setter to work around that.
This is discussed as being a breaking change above, and I'm personally
okay with a dev note on this point rather than allowing the edge case.
That said, here's a simple example:
```
function test_changed_behavior() {
$user = new WP_User(1);
error_log(var_export($user, true)); // `roles` shows as array()
error_log(var_export($user->roles, true)); // `roles` shows as
array( 'administrator' )
// these worked before the change, but not after. Each gives a
warning: `Indirect modification of overloaded property`
array_shift( $user->roles );
$user->roles[] = 'subscriber';
$user->roles[0] = 'editor';
error_log(var_export($user->roles, true)); // `roles` shows as
array( 'administrator' )
}
add_action('wp_footer', 'test_changed_behavior');
function test_mitigation() {
$user = new WP_User(1);
error_log(var_export($user, true)); // `roles` shows as array()
error_log(var_export($user->roles, true)); // `roles` shows as
array( 'administrator' )
// Workaround: modify a different var
$roles = $user->roles;
array_shift( $roles );
$roles[] = 'subscriber';
$roles[0] = 'editor';
$user->roles = $roles;
error_log(var_export($user->roles, true)); // `roles` shows as
array( 'administrator' )
}
add_action('wp_footer', 'test_mitigation');
```
--
Ticket URL: <https://core.trac.wordpress.org/ticket/58001#comment:43>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list