Opened 5 months ago
Last modified 6 days ago
#22921 new enhancement
Allow get_users() to return array of values via 'fields' parameter
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Priority: | normal | Milestone: | Future Release |
| Component: | Users | Version: | 3.5 |
| Severity: | normal | Keywords: | has-patch needs-testing |
| Cc: |
Description
Currently, the 'fields' parameter in the arguments array for get_users() only accepts either an array of user data fields, or the string 'all'. Both of these options cause get_users() to return an array of object comprised of the specified user data. Passing any other string value to 'fields' causes get_users() to return an array of user IDs.
Per the Codex:
Array of objects, except when fields specifies a single field to be returned, then an array of values is returned. If fields is set to all_with_meta, it will return an array of WP_User objects.
This statement appears to be untrue, but would be incredibly useful if it were true.
Patch adds this functionality to get_users().
Potentially related: #18581
Attachments (1)
Change History (12)
chipbennett — 5 months ago
comment:2
chipbennett — 5 months ago
Return an array of user email addresses, such as:
$user_emails = get_users( array( 'fields' => 'user_email' ) );
This usage eliminates the step of looping through the array of objects otherwise returned, to pluck out the email addresses.
comment:3
DavidAnderson — 5 months ago
-1 from me.
I also had to waste some time when dealing with this function, and the difference between Codex and the actual behaviour.
However, once I worked the actual behaviour out, I wrote my code to deal with that reality. If you change the behaviour, you'll break lots of existing code, and people will be confused/annoyed when their sites break and they have to re-write. Better solution is to change Codex to describe the current real behaviour.
If you change the behaviour, you'll break lots of existing code
If you take a look at the patch, the only code that will break, are those passing the fields parameter as one of the following, and expecting back a list of user_id's, a broken assumption and code to start with..
array( 'ID', 'user_login', 'user_pass', 'user_nicename', 'user_email', 'user_url', 'user_registered', 'user_activation_key', 'user_status', 'display_name' )
comment:5
in reply to:
↑ 4
;
follow-up:
↓ 6
DavidAnderson — 5 months ago
dd32: Yes, that's right - it'll break code that uses the existing function. I've written such code. The existing function does something useful, and works whilst doing it, and people are using it. There's a real-world cost to breaking that.
comment:6
in reply to:
↑ 5
;
follow-up:
↓ 7
chipbennett — 5 months ago
Replying to DavidAnderson:
dd32: Yes, that's right - it'll break code that uses the existing function. I've written such code. The existing function does something useful, and works whilst doing it, and people are using it. There's a real-world cost to breaking that.
Let's consider the purpose of the 'fields' array parameter: to return only the fields specified, instead of all user data. The code provides two forms of output, based on the type of input:
- An array of objects comprised of one or more values, if 'fields' => array( $fields ) is passed
- An array of values, if 'fields' => $field is passed
Thus, the only way this patch would break existing code is if someone passed a field other than 'ID' for 'fields', e.g.:
$user_IDs = get_users( array( 'fields' => 'user_email' ) );
...and then used the output as if an array of IDs was the expected return value.
That just doesn't make logical sense. Why would someone pass 'user_email' as the value for 'fields', and then subsequently use the output as if 'ID' had been passed?
Any normal developer would look at that output and do one of two things:
- Change the function call to 'fields' => 'ID', if the desired return value is 'ID'
- Change the function call to pass 'fields' => array( 'user_email' ) if the desired return value is 'user_email'
I contend that if a developer leaves the code as-is, the user code is at fault, and such a use case shouldn't be something that keeps the core function itself from being improved.
comment:7
in reply to:
↑ 6
;
follow-up:
↓ 8
DavidAnderson — 5 months ago
Aah - gotcha. Sorry, I was confusing myself before. You are completely right ...
... up to a point (unless I'm still confused!).
What you desire can already be done, using this syntax (which I use in the "Use Admin Password" plugin):
$desired_fields = get_users("fields[]=email");
So I think we just need to change Codex to give an accurate description, rather than re-add the same feature?
comment:8
in reply to:
↑ 7
;
follow-up:
↓ 9
chipbennett — 5 months ago
Replying to DavidAnderson:
Aah - gotcha. Sorry, I was confusing myself before. You are completely right ...
... up to a point (unless I'm still confused!).
What you desire can already be done, using this syntax (which I use in the "Use Admin Password" plugin):
$desired_fields = get_users("fields[]=email");So I think we just need to change Codex to give an accurate description, rather than re-add the same feature?
Is that any different than:
$desired_fields = get_users( array( 'fields' => array( 'user_email' ) ) );
If so, then that still doesn't return the desired output. That returns an array of objects, each of which contains one entity, 'user_email'.
So, when 'ID' is passed as the single field, the output is an array of user IDs; but if any other field is passed as the single field, an array of objects is returned, since the only possible way to pass a single field other than ID is by passing 'fields' as an array.
So, user IDs can be returned as a simple array, like so:
$user_IDs = get_users( array( 'fields' => 'ID' ) );
$user IDs = array(
[0] => '1',
[1] => '2',
[2] => '3'
);
But to get a single-field value for any other field, you can only get an array of objects:
$user_emails = get_users( array( 'fields' => array( 'user_email' ) ) );
$user_emails = array(
[0] => object( 'user_email' => 'email@...' ),
[1] => object( 'user_email' => 'email@...' ),
[2] => object( 'user_email' => 'email@...' )
);
The purpose of this ticket is to allow for consistent return for single-field values for fields other than 'ID'; e.g. so that the following return is possible:
$user_IDs = get_users( array( 'fields' => 'email' ) );
$user IDs = array(
[0] => 'email@...',
[1] => 'email@...',
[2] => 'email@...'
);
Currently this return is not possible, requiring a wasteful, second step to loop through the array of objects to pluck the field values.
comment:9
in reply to:
↑ 8
DavidAnderson — 5 months ago
OK... but I'm still missing something... the original bug report spoke of adding something "incredibly useful"... but the difference is just that you can get back an array of strings instead of an array of objects (with each object containing the string as a property)? I feel entirely indifferent to that change and leave it to others better qualified to judge on what would be usual WP practice on such things.
comment:11
ryan — 6 days ago
- Milestone changed from 3.6 to Future Release

Example usage?