16

Is there any way to check if a user id exists? I want to create a function similar to username_exists() but which returns if the id exists or not.

6 Answers 6

2

Use this function:

function user_id_exists($user){

    global $wpdb;

    $count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $wpdb->users WHERE ID = %d", $user));

    if($count == 1){ return true; }else{ return false; }

}

Usage:

if(user_id_exists(1)){ 
    //it does exists
} else {
    //it doesn't
}
2
  • 10
    also you can use this method too: $user = get_userdata( $user_id ); if ( $user == false ){ //user id does not exist } else { //user id exists
    – Dan
    Oct 17, 2014 at 14:27
  • WP has evolved but this is still very relevant. @Dan's answer is the way to go. Alternatively, get_user_by('id', $user_id) also works wonders. In any case, throwing a SQL query just for that is overkill.
    – Buzut
    Jun 9, 2022 at 9:25
47

I would highly recommend Daniel's much simpler solution over the one currently selected as correct:

$user = get_userdata( $user_id );
if ( $user === false ) {
    //user id does not exist
} else {
    //user id exists
}
2
  • 1
    I like this one far more than creating a own function just for this. In my case i had to work with the userdata anyway so … +1
    – GDY
    Mar 29, 2018 at 17:10
  • If there is an array of user IDs and you need to remove the deleted/not existing users, this can be used as array_filter callback: $user_ids = array_filter( $user_ids, 'get_userdata' ); Oct 2, 2019 at 17:55
6

In this case I will definetely not use the get_userdata( $user_id ) while it is returning a WP_User, so it is more greedy than just a custom query.

About the query, I agree using the prepare method, but the SELECT COUNT(*) means you are returning all columns, which is useless here.

I would recommend using SELECT COUNT(ID) unstead, in this way we are only working on a single column which will be faster.

On other aspect for the returning statement, it would be more readable with a Ternary Logic like :

return 1 < $count ? true : false;

To sum up, I wouldd have implemented it like :

function user_id_exists( $user_id ) {
    global $wpdb;
    $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(ID) FROM $wpdb->users WHERE ID = %d", $user_id ) );
    return empty( $count ) || 1 > $count ? false : true;
}
2
  • 1
    Just FYI SELECT COUNT(*) and SELECT COUNT(ID) both return a single column... a count. Apr 13, 2019 at 17:12
  • This is well argument and makes sense. It actually all depends on where this is executed. If it's somewhere the user has been fetched from DB already, data is cached so the get_userdata won't hurt.
    – Buzut
    Jun 9, 2022 at 9:30
3

If performance is a concern, use:

function user_id_exists($user_id) {
    global $wpdb;

    // Check cache:
    if (wp_cache_get($user_id, 'users')) return true;

    // Check database:
    if ($wpdb->get_var($wpdb->prepare("SELECT EXISTS (SELECT 1 FROM $wpdb->users WHERE ID = %d)", $user_id))) return true;

    return false;
}

Otherwise, use get_userdata($user_id) !== false. The call to get_userdata will retrieve a whole row from the database instead of a single value, create a new WP_User object and cache it on success.

1

Something that is done by at least a few hackers ( I know because I played victim to this at least once) is to visit your site using this type of URL

domain.com/?author=0

domain.com/?author=1

etc.

On a successful attempt the output of the site will have valid data, in addition the user nicename will be in the content of the website and the nickname may be there as well (depending on the pages output).

On an invalid attempt the site will go to the 404 page (or whatever is set to happen on a page not found error).

It can be rather trivial to build a script using cURL that can test from say author=0 up to author=999 in a relatively short amount of time and output a list of usernames. I had a hacker do this for one of my sites and then try to login to each user by using another list of popular passwords.

As you can imagine the first time this happens it is a bit scary to see that someone can quite easily find out all your usernames. Lucky for me strong passwords saved the day that time, I'm sure not everyone is so lucky.

I have tested this against a couple big name websites (who will remain nameless in this post) and it seems that there may be nothing anyone can do as of yet to stop this from happening. I personally think it is security risk that wordpress should close.

EDIT:

Here in the future (early 2016) I now know that there are methods/plugins which can thwart this user enumeration attack. And I further have changed my stance on the security risk of this and I no longer think WordPress should change this.

1
  • In any case, you need to limit the login failed attempts. After 3 to 5 fails in less than 5 minutes, you can block the user for some time. This'll really slow down dictionary or brute force attacks.
    – Buzut
    Jun 9, 2022 at 9:33
0

Try This will not Showing you the warning like Missing argument 2 for wpdb::prepare()

function user_id_exists($user_id){
    global $wpdb;
    $count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $wpdb->users WHERE ID = %d",$user_id));
    if($count == 1){ return true; }else{ return false; }
}
2
  • You can just write return $count == 1;
    – fuxia
    Jun 12, 2015 at 10:02
  • i need to just check the user exist or not and when i call the function like : if(!user_id_exists($userId)){ // do stuffs when user not exists }
    – Anand
    Jun 12, 2015 at 10:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.