WordPress源码深度解析之:`wp-includes/class-wp-user.php`:用户对象与权限验证的底层逻辑。

各位观众老爷们,晚上好!我是你们的老朋友,今天咱们来聊聊WordPress源码里一个非常重要的文件——wp-includes/class-wp-user.php。这个文件里藏着WordPress用户对象的秘密,以及权限验证的底层逻辑。别看它名字平平无奇,但它却是你理解WordPress用户管理和权限控制的关键钥匙。

咱们今天就用“扒皮抽筋”的方式,把这个文件给它彻底解剖一下,保证让你看完之后,对WordPress的用户系统有个更深的认识。

一、开场白:WP_User类的前世今生

在WordPress的世界里,每一个用户都代表着一个WP_User类的实例。这个类封装了用户的各种信息,比如用户名、密码、邮箱、角色等等。它就像一个“用户数据包”,里面塞满了关于这个用户的各种属性。

WP_User类主要负责以下几个任务:

  • 获取和设置用户信息: 从数据库中读取用户的各种信息,并允许你修改这些信息。
  • 权限验证: 判断用户是否具有执行特定操作的权限。
  • 角色管理: 管理用户的角色,并根据角色赋予相应的权限。

二、WP_User类的核心属性和方法

要了解WP_User类,首先要熟悉它的核心属性和方法。

2.1 核心属性

属性名 数据类型 描述
$data array 存储用户数据的关联数组。比如 $data['user_login'] 存储用户名,$data['user_email'] 存储邮箱。
$ID int 用户ID。
$caps array 用户拥有的所有权限的数组。这个数组是通过用户的角色和单独赋予的权限计算出来的。
$roles array 用户拥有的角色数组。
$allcaps array 用户所有可能的权限。这个属性很少直接使用。
$filter string 用于过滤用户数据的过滤器名称。默认是 ‘raw’,表示未经任何处理的原始数据。

2.2 核心方法

方法名 描述
__construct( $id = 0, $name = '', $site_id = '' ) 构造函数。用于创建一个WP_User对象。可以传入用户ID,用户名,站点ID等参数。
get( $key, $filter = 'raw' ) 获取用户数据。$key 是要获取的数据的键名,$filter 是过滤器名称。例如,$user->get( 'user_login' ) 可以获取用户名。
has_cap( $cap ) 判断用户是否具有某个权限。$cap 是要判断的权限名称。例如,$user->has_cap( 'edit_posts' ) 可以判断用户是否具有编辑文章的权限。
add_role( $role ) 给用户添加一个角色。$role 是要添加的角色名称。
remove_role( $role ) 移除用户的某个角色。$role 是要移除的角色名称。
set_role( $role ) 设置用户的角色。注意,这个方法会移除用户的所有现有角色,然后添加新的角色。$role 是要设置的角色名称。
get_role_caps() 获取用户所有角色的权限。
update_user_level_from_caps() 根据用户的权限更新用户等级(user_level)。这个等级在WordPress 2.x时代使用,现在已经基本被角色和权限系统取代。

三、WP_User类的构造函数:__construct()

WP_User类的构造函数是创建用户对象的第一步。它的主要作用是从数据库中读取用户的各种信息,并初始化对象的属性。

public function __construct( $id = 0, $name = '', $site_id = '' ) {
    if ( ! empty( $id ) ) {
        $this->init( $id, $name, $site_id );
    }
}

这个构造函数接受三个参数:

  • $id: 用户ID。
  • $name: 用户名。
  • $site_id: 站点ID(用于多站点环境)。

如果传入了用户ID,构造函数会调用init()方法来初始化用户对象。

四、init()方法:初始化用户对象

init()方法是WP_User类中非常重要的一个方法。它负责从数据库中读取用户的各种信息,并设置对象的属性。

protected function init( $id, $name = '', $site_id = '' ) {
    global $wpdb, $wp_roles;

    $id = (int) $id;

    if ( ! empty( $id ) ) {
        $data = get_userdata( $id );

        if ( false === $data ) {
            $this->data = new stdClass();
            $this->ID = 0;
            return;
        }
    } elseif ( ! empty( $name ) ) {
        $data = get_user_by( 'login', $name );

        if ( false === $data ) {
            $this->data = new stdClass();
            $this->ID = 0;
            return;
        }
    } else {
        $this->data = new stdClass();
        $this->ID = 0;
        return;
    }

    $this->data = $data->data;
    $this->ID = (int) $data->ID;
    $this->caps = apply_filters( 'user_caps', $this->get_caps_from_db(), $this );
    $this->roles = (array) get_user_meta( $this->ID, $wpdb->prefix . 'capabilities', true );
    $this->allcaps = apply_filters( 'user_has_cap', $wp_roles->get_role_caps( $this->roles ), $this->caps, $this->name );
    $this->filter = 'edit';

    $this->update_user_level_from_caps();
}

这个方法做了以下几件事:

  1. 获取用户数据: 根据用户ID或用户名,从数据库中获取用户数据。这里使用了get_userdata()get_user_by()函数。
  2. 设置对象属性: 将获取到的用户数据设置到对象的$data$ID$caps$roles$allcaps属性中。
  3. 获取用户权限: 调用get_caps_from_db()方法从数据库中获取用户的权限,并使用apply_filters()函数对权限进行过滤。
  4. 获取用户角色: 从用户元数据中获取用户的角色。
  5. 更新用户等级: 调用update_user_level_from_caps()方法更新用户等级。

五、get_caps_from_db()方法:从数据库中获取用户权限

get_caps_from_db()方法负责从数据库中获取用户的权限。它主要通过查询wp_usermeta表,获取用户角色对应的权限。

protected function get_caps_from_db() {
    global $wpdb;

    $caps = get_user_meta( $this->ID, $wpdb->prefix . 'capabilities', true );

    if ( ! is_array( $caps ) ) {
        return array();
    }

    return $caps;
}

这个方法很简单,就是从wp_usermeta表中读取wp_capabilities这个元数据,这个元数据存储了用户角色的信息。

六、has_cap()方法:权限验证的核心

has_cap()方法是WP_User类中最重要的方法之一。它负责判断用户是否具有某个权限。

public function has_cap( $cap ) {
    global $wp_roles;

    $args = array_slice( func_get_args(), 1 );
    $args = array_merge( array( $cap, $this->ID ), $args );

    $caps = apply_filters( 'user_has_cap', $this->allcaps, $args, $this );

    if ( ! empty( $caps[ $cap ] ) ) {
        return apply_filters( 'user_has_cap_default', $caps[ $cap ], $cap, $this->ID, $args );
    } else {
        return apply_filters( 'user_has_cap_default', false, $cap, $this->ID, $args );
    }
}

这个方法的工作流程如下:

  1. 获取参数: 获取传递给has_cap()方法的参数。
  2. 应用过滤器: 使用apply_filters()函数对用户的权限进行过滤。user_has_cap 过滤器允许插件和主题修改用户的权限。
  3. 判断权限: 判断用户的权限数组中是否包含要判断的权限。
  4. 返回结果: 如果用户具有该权限,返回 true,否则返回 false

举个例子:

假设我们要判断用户是否具有编辑文章的权限:

$user = wp_get_current_user();
if ( $user->has_cap( 'edit_posts' ) ) {
    echo '用户具有编辑文章的权限';
} else {
    echo '用户不具有编辑文章的权限';
}

七、角色管理方法:add_role()remove_role()set_role()

WP_User类还提供了一些方法来管理用户的角色:

  • add_role( $role ) 给用户添加一个角色。
  • remove_role( $role ) 移除用户的某个角色。
  • set_role( $role ) 设置用户的角色。
public function add_role( $role ) {
    if ( empty( $role ) ) {
        return;
    }

    if ( ! in_array( $role, $this->roles ) ) {
        $this->roles[] = $role;
        $this->roles = array_unique( $this->roles );
        $this->update_caps();
    }
}

public function remove_role( $role ) {
    if ( empty( $role ) ) {
        return;
    }

    $key = array_search( $role, $this->roles );
    if ( false !== $key ) {
        unset( $this->roles[ $key ] );
        $this->update_caps();
    }
}

public function set_role( $role ) {
    if ( empty( $role ) ) {
        $this->roles = array();
    } else {
        $this->roles = array( $role );
    }

    $this->update_caps();
}

这三个方法都会调用update_caps()方法来更新用户的权限。

八、update_caps()方法:更新用户权限

update_caps()方法负责更新用户的权限。它会重新计算用户的权限,并将权限保存到数据库中。

protected function update_caps() {
    global $wpdb, $wp_roles;

    $this->caps = apply_filters( 'user_caps', $this->get_caps_from_db(), $this );
    $this->allcaps = apply_filters( 'user_has_cap', $wp_roles->get_role_caps( $this->roles ), $this->caps, $this->name );

    update_user_meta( $this->ID, $wpdb->prefix . 'capabilities', $this->roles );
}

这个方法做了以下几件事:

  1. 获取用户权限: 调用get_caps_from_db()方法从数据库中获取用户的权限。
  2. 获取用户角色权限: 调用$wp_roles->get_role_caps()方法获取用户角色对应的权限。
  3. 合并权限: 将用户的权限和角色权限合并。
  4. 保存权限: 将用户的角色信息保存到wp_usermeta表中。

九、get()方法:获取用户数据

get()方法用于获取用户数据。它可以获取用户对象的任何属性。

public function get( $key, $filter = 'raw' ) {
    if ( 'ID' === $key ) {
        return $this->ID;
    }

    if ( isset( $this->data->$key ) ) {
        $value = $this->data->$key;
    } else {
        return null;
    }

    if ( 'raw' === $filter ) {
        return $value;
    }

    return sanitize_user_field( $key, $value, $this->ID, $filter );
}

这个方法接受两个参数:

  • $key: 要获取的数据的键名。
  • $filter: 过滤器名称。

举个例子:

$user = wp_get_current_user();
$username = $user->get( 'user_login' ); // 获取用户名
$email = $user->get( 'user_email' );   // 获取邮箱

十、总结:WP_User类的价值和意义

WP_User类是WordPress用户系统的核心。它封装了用户的各种信息,并提供了权限验证和角色管理的功能。理解WP_User类对于理解WordPress的用户管理和权限控制至关重要。

通过今天的“扒皮抽筋”,相信你已经对WP_User类有了更深入的认识。下次再遇到用户权限相关的问题,你就可以胸有成竹,轻松应对了。

十一、思考题

  1. WP_User类是如何与WordPress的角色和权限系统协同工作的?
  2. 如何使用user_has_cap过滤器来修改用户的权限?
  3. WP_User类在多站点环境中有什么特殊之处?

希望大家多多思考,多多实践,才能真正掌握WordPress的精髓。

今天的分享就到这里,感谢大家的观看!咱们下次再见!

发表回复

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