阐述 `get_user_by()` 函数的源码,它如何通过 `ID`、`slug` 或 `email` 查询用户数据。

大家好,今天我们来聊聊 WordPress 里的一个明星函数:get_user_by()。这哥们儿可是个找人的高手,你给他一个 ID、slug 或者 email,他就能帮你把用户的信息给揪出来。听起来是不是很神奇?别急,咱们一层一层地扒开他的源码,看看他到底是怎么做到的。

先来打个招呼:嘿,朋友们,准备好迎接一场源码探险了吗? Let’s go!

1. get_user_by() 函数的基本结构

首先,我们来看一下 get_user_by() 函数的基本骨架(为了方便理解,这里做了一些简化,略去了错误处理和一些兼容性代码):

function get_user_by( $field, $value ) {
    global $wpdb;

    $user = false;

    switch ( $field ) {
        case 'id':
            $user = get_userdata( $value );
            break;

        case 'slug':
            $user = get_user_by_slug( $value );
            break;

        case 'email':
            $user = get_user_by_email( $value );
            break;

        // ... 其他 field 类型

        default:
            return false; // 如果 field 不支持,直接返回 false
    }

    return $user;
}

看到了吧?其实 get_user_by() 本身并不做太多的事情,它更像是一个调度员,根据你提供的 $field 参数,把任务分发给不同的函数去处理。

  • $field: 你想用什么字段来查找用户,比如 ‘id’,’slug’,’email’ 等等。
  • $value: 你要查找的字段对应的值,比如 ID 是 1,slug 是 ‘john-doe’,email 是 ‘[email protected]’。

2. 通过 ID 查找用户:get_userdata()

如果 $field 是 ‘id’,那么 get_user_by() 会调用 get_userdata() 函数。 get_userdata() 才是真正从数据库里捞数据的。

function get_userdata( $user_id ) {
    global $wpdb, $_wp_cached_userdata;

    $user_id = (int) $user_id;

    if ( isset( $_wp_cached_userdata[ $user_id ] ) ) {
        return $_wp_cached_userdata[ $user_id ]; // 先从缓存里找
    }

    $data = WP_User::get_data_by( 'id', $user_id );

    if ( ! $data ) {
        return false; // 找不到就返回 false
    }

    $user = new WP_User( $data->ID, '', $data );

    $_wp_cached_userdata[ $user_id ] = $user; // 存到缓存里

    return $user;
}
  • 缓存优先: 首先,get_userdata() 会检查全局变量 $_wp_cached_userdata,看看这个用户的信息是不是已经缓存过了。 如果缓存命中,那就直接返回缓存里的数据,速度杠杠的!
  • 从数据库捞数据: 如果缓存没命中,那就调用 WP_User::get_data_by( 'id', $user_id ),从数据库里获取用户数据。
  • 创建 WP_User 对象: 拿到数据后,会创建一个 WP_User 对象,这个对象包含了用户的所有信息,比如用户名、邮箱、角色等等。
  • 存入缓存: 最后,把这个 WP_User 对象存到缓存里,下次再找这个用户就不用再去数据库了。

WP_User::get_data_by() 内部实现 (简化版):

class WP_User {
    public static function get_data_by( $field, $value ) {
        global $wpdb;

        $field = sanitize_key( $field );
        $value = sanitize_text_field( $value );

        $table = $wpdb->users;
        $sql = $wpdb->prepare( "SELECT * FROM $table WHERE $field = %s", $value );

        $userdata = $wpdb->get_row( $sql );

        return $userdata;
    }
}

这个函数其实就是构建一个 SQL 查询语句,然后从 wp_users 表里把数据捞出来。

3. 通过 Slug 查找用户:get_user_by_slug()

如果 $field 是 ‘slug’,get_user_by() 会调用 get_user_by_slug() 函数。 Slug 可以理解为用户的昵称或者别名,通常是 URL 友好的。

function get_user_by_slug( $slug ) {
    global $wpdb, $_wp_cached_users;

    $user = false;

    if ( isset( $_wp_cached_users['slug:' . $slug] ) ) {
        return $_wp_cached_users['slug:' . $slug]; // 先从缓存里找
    }

    $user = get_user_by( 'login', $slug );  // 尝试login字段

    if ( !$user ){ // 如果没找到, 尝试 user_nicename

      $user_query = new WP_User_Query( array(
          'nicename' => $slug,
          'number' => 1,
          'count_total' => false,
      ) );

      $users = $user_query->get_results();

      if ( ! empty( $users ) ) {
          $user = $users[0];
      }
    }

    if ( $user ) {
        $_wp_cached_users['slug:' . $slug] = $user; // 存到缓存里
    }

    return $user;
}
  • 缓存优先:get_userdata() 一样,先检查缓存。
  • 尝试Login字段: 先尝试用login字段(用户名)找用户, 历史原因导致.
  • 使用 WP_User_Query 如果login字段没找到, 使用 WP_User_Query 类来查询 wp_users 表,查找 user_nicename 字段是否匹配。
  • 创建 WP_User 对象: 如果找到了,同样会创建一个 WP_User 对象。
  • 存入缓存: 最后,把这个 WP_User 对象存到缓存里。

4. 通过 Email 查找用户:get_user_by_email()

如果 $field 是 ’email’,get_user_by() 会调用 get_user_by_email() 函数。

function get_user_by_email( $email ) {
    global $wpdb, $_wp_cached_users;

    $user = false;

    if ( isset( $_wp_cached_users['email:' . $email] ) ) {
        return $_wp_cached_users['email:' . $email]; // 先从缓存里找
    }

    $user = get_user_by( 'email', $email ); // 递归调用自身

    if ( !$user ){

      $sql = $wpdb->prepare( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'email' AND meta_value = %s", $email );

      $user_id = $wpdb->get_var( $sql );

      if ( $user_id ) {
          $user = get_userdata( $user_id );
      }
    }

    if ( $user ) {
        $_wp_cached_users['email:' . $email] = $user; // 存到缓存里
    }

    return $user;
}
  • 缓存优先: 还是老套路,先检查缓存。
  • 使用 usermeta 表: Email 信息实际上是存储在 wp_usermeta 表里的,所以需要查询这个表。
  • 获取 User ID: 先从 wp_usermeta 表里找到 email 对应的 user_id
  • 调用 get_userdata() 拿到 user_id 后,再调用 get_userdata() 函数,根据 ID 获取用户的完整信息。
  • 创建 WP_User 对象: get_userdata() 会创建 WP_User 对象。
  • 存入缓存: 最后,把这个 WP_User 对象存到缓存里。

5. 缓存机制的重要性

大家可能注意到了,无论是 get_userdata()get_user_by_slug() 还是 get_user_by_email(),都使用了缓存机制。 这是因为从数据库里读取数据是一个比较耗时的操作,如果每次都去数据库查,性能会很差。 通过缓存,可以大大提高查询速度,减轻数据库的压力。

WordPress 使用了全局变量 $_wp_cached_userdata$_wp_cached_users 来存储缓存数据。

6. WP_User 对象

前面提到了 WP_User 对象,这个对象非常重要,它包含了用户的所有信息。 我们可以通过 WP_User 对象的属性来访问用户的信息,比如:

$user = get_user_by( 'id', 1 );

if ( $user ) {
    echo '用户名:' . $user->user_login . '<br>';
    echo '邮箱:' . $user->user_email . '<br>';
    echo '昵称:' . $user->display_name . '<br>';
    echo '用户ID: ' . $user->ID . '<br>';
} else {
    echo '找不到用户!';
}

7. 总结

好啦,讲了这么多,我们来总结一下 get_user_by() 函数的工作流程:

Field 调用函数 主要步骤
‘id’ get_userdata() 1. 检查缓存。 2. 调用 WP_User::get_data_by()wp_users 表里根据 ID 获取数据。 3. 创建 WP_User 对象。 4. 存入缓存。
‘slug’ get_user_by_slug() 1. 检查缓存。 2. 尝试用用户名(login)查找用户. 3. 使用 WP_User_Querywp_users 表里根据 user_nicename 获取数据。 4. 创建 WP_User 对象。 5. 存入缓存。
’email’ get_user_by_email() 1. 检查缓存。 2. 从 wp_usermeta 表里根据 email 获取 user_id。 3. 调用 get_userdata() 根据 user_id 获取用户的完整信息。 4. 创建 WP_User 对象(在 get_userdata() 中)。 5. 存入缓存。

8. 补充说明和注意事项

  • 安全性: 在实际使用中,一定要注意对 $value 进行适当的验证和过滤,防止 SQL 注入等安全问题。 WordPress 已经做了一些基本的安全处理,比如 sanitize_key()sanitize_text_field(),但我们仍然需要保持警惕。
  • 性能优化: 虽然 get_user_by() 使用了缓存,但在高并发的情况下,仍然可能成为性能瓶颈。 可以考虑使用更高级的缓存技术,比如 Redis 或 Memcached。
  • 扩展性: get_user_by() 函数也提供了扩展机制,可以通过 get_user_by filter 来添加自定义的 field 类型。

9. 举个例子

假设我们要通过 email 查找用户,可以这样写:

$email = '[email protected]';
$user = get_user_by( 'email', $email );

if ( $user ) {
    echo '用户名:' . $user->user_login . '<br>';
} else {
    echo '找不到邮箱为 ' . $email . ' 的用户!';
}

10. 总结的总结

get_user_by() 函数是 WordPress 中一个非常常用的函数,它提供了一种方便的方式来根据 ID、slug 或 email 查找用户。 通过深入了解它的源码,我们可以更好地理解 WordPress 的内部机制,并且可以更好地优化我们的代码。

希望今天的讲座对大家有所帮助! 记住,源码是最好的老师,多看源码,多思考,你也能成为 WordPress 大师!

好了,今天的源码探险就到这里。希望大家下次再来玩!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注