阐述 `WP_User` 类的源码,特别是它如何封装用户数据和权限信息。

各位观众老爷们,大家好!今天咱们来聊聊WordPress里一个非常重要的角色——WP_User 类。这玩意儿就像WordPress世界里的“居民身份证”,记录了用户的所有信息,还管着用户的“权限护照”。

一、WP_User 类:用户信息的集散地

简单来说,WP_User 类是一个PHP类,它主要负责从数据库中提取用户数据,并将这些数据封装成一个对象。你可以把它想象成一个“用户数据容器”,里面装着用户的各种属性,比如用户名、邮箱、角色等等。

1.1 构造函数:数据的初始化

WP_User 类的构造函数是它生命周期的起点。它接收一个用户ID(或用户名)作为参数,然后根据这个ID从数据库中获取用户数据,并填充到对象的属性中。

/**
 * WordPress User class.
 *
 * @since 2.0.0
 */
class WP_User {

    /**
     * User data.
     *
     * @since 2.0.0
     * @access public
     * @var stdClass
     */
    public $data;

    /**
     * The user's ID.
     *
     * @since 2.1.0
     * @access public
     * @var int
     */
    public $ID = 0;

    /**
     * The user's capabilities.
     *
     * @since 2.0.0
     * @access public
     * @var array
     */
    public $caps = array();

    /**
     * User metadata.
     *
     * @since 2.0.0
     * @access public
     * @var array
     */
    public $meta_value = array();

    /**
     * The roles the user is part of.
     *
     * @since 2.0.0
     * @access public
     * @var array
     */
    public $roles = array();

    /**
     * All capabilities the user has, including primitive and derived ones.
     *
     * @since 2.0.0
     * @access public
     * @var array
     */
    public $allcaps = array();

    /**
     * The filter context.
     *
     * @since 2.9.0
     * @access public
     * @var string
     */
    public $filter = null;

    /**
     * Constructor.
     *
     * Retrieves the userdata and populates the class variables.
     *
     * @since 2.0.0
     * @access public
     *
     * @global wpdb $wpdb WordPress database abstraction object.
     *
     * @param int|string|WP_User|stdClass $id Optional. User ID, username, WP_User object, or
     *                                        STD Object of user data. Default 0.
     * @param string                         $name Optional. User's username. Default empty.
     */
    public function __construct( $id = 0, $name = '' ) {
        global $wpdb;

        if ( is_object( $id ) ) {
            // copy properties of WP_User object.
            if ( is_a( $id, 'WP_User' ) ) {
                foreach ( get_object_vars( $id ) as $key => $value ) {
                    $this->$key = $value;
                }
                return;
            } elseif ( isset( $id->data ) ) {
                $this->data = $id->data;
                $this->ID   = (int) $id->ID;
                $this->get_role_caps();
                return;
            } else {
                $this->data = $id;
                $this->ID   = (int) $id->ID;
                $this->get_role_caps();
                return;
            }
        }

        if ( ! empty( $id ) ) {
            if ( is_numeric( $id ) ) {
                $id = (int) $id;
                $data = get_userdata( $id );
            } else {
                $data = get_user_by( 'login', $id );
            }

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

        // No user found.
        if ( empty( $this->ID ) ) {
            $this->data = new stdClass();
            return;
        }

        $this->get_role_caps();
    }
}

这个构造函数的功能可以概括为:

  • 接收参数: 可以接收用户ID、用户名、WP_User对象或包含用户数据的stdClass对象。
  • 获取数据: 根据传入的参数,通过get_userdata()get_user_by()函数从数据库中获取用户数据。
  • 填充属性: 将获取到的用户数据填充到$data$ID等属性中。
  • 获取角色权限: 调用get_role_caps()方法,根据用户的角色获取其权限。

1.2 核心属性:用户信息的关键

WP_User 类中定义了一些非常重要的属性,它们存储了用户的关键信息:

属性名 数据类型 描述
$data stdClass 包含用户数据的对象,例如用户名、密码(加密后的)、邮箱、注册时间等。
$ID int 用户的ID。
$caps array 用户拥有的权限列表,例如readedit_posts等。这些权限是直接分配给用户的,而不是通过角色继承的。
$roles array 用户所属的角色列表,例如administratoreditorauthor等。一个用户可以拥有多个角色。
$allcaps array 用户拥有的所有权限列表,包括直接分配的权限和通过角色继承的权限。这个属性是权限判断的关键。
$meta_value array 用户元数据,这是一个关联数组,可以存储用户的自定义信息,例如用户的个人简介、社交账号等。这些数据存储在wp_usermeta表中。
$filter string 过滤器的上下文,用于在获取用户数据时应用过滤器。

1.3 数据访问:获取用户信息的途径

要访问WP_User 对象中的数据,你可以直接访问它的属性,例如:

$user = wp_get_current_user(); // 获取当前用户对象
echo '用户名:' . $user->user_login; // 输出用户名 (不推荐,推荐使用下面的方法)
echo '用户ID:' . $user->ID; // 输出用户ID

但是,更推荐使用WordPress提供的专门的函数来获取用户信息,例如:

$user = wp_get_current_user();
echo '用户名:' . $user->get('user_login');
echo '用户邮箱:' . $user->get('user_email');
echo '用户注册时间:' . $user->get('user_registered');

使用$user->get()方法的好处是,它可以应用过滤器,对数据进行处理,保证数据的安全性和一致性。

二、权限管理:WP_User 的“权力游戏”

WP_User 类不仅存储用户数据,还负责管理用户的权限。WordPress的权限系统非常灵活,允许你为不同的用户分配不同的权限,从而控制他们对网站的访问和操作。

2.1 角色的概念:权限的集合

在WordPress中,角色是一组权限的集合。例如,administrator角色拥有最高的权限,可以管理网站的所有内容和设置;editor角色可以编辑和发布文章;author角色只能编辑和发布自己的文章;contributor角色只能撰写文章,不能发布;subscriber角色只能阅读文章。

WordPress默认提供了以下几个角色:

角色名 描述
administrator 拥有最高权限,可以管理网站的所有内容和设置,包括用户管理、主题和插件管理等。
editor 可以编辑和发布所有文章,包括其他用户的文章。还可以管理分类、标签和媒体文件。
author 可以编辑和发布自己的文章。还可以上传媒体文件。
contributor 可以撰写文章,但不能发布。需要经过editoradministrator审核才能发布。
subscriber 只能阅读文章和评论。

2.2 权限的授予:add_cap()remove_cap()

WordPress允许你为用户或角色授予或撤销特定的权限。你可以使用add_cap()remove_cap()函数来实现:

  • add_cap( string $role, string $cap, bool $grant = true ): 为指定的角色添加权限。
  • remove_cap( string $role, string $cap ): 从指定的角色移除权限。

例如,要为editor角色添加manage_options权限,可以使用以下代码:

$role = get_role( 'editor' );
$role->add_cap( 'manage_options' );

要为一个用户添加权限,需要先获取用户对象,然后使用add_cap()方法:

$user = get_user_by( 'login', 'john' ); // 获取用户名为john的用户对象
$user->add_cap( 'edit_posts' ); // 为用户添加编辑文章的权限

2.3 权限的判断:current_user_can()

判断当前用户是否拥有某个权限,可以使用current_user_can()函数:

if ( current_user_can( 'edit_posts' ) ) {
    // 当前用户拥有编辑文章的权限
    echo '你可以编辑文章';
} else {
    // 当前用户没有编辑文章的权限
    echo '你没有权限编辑文章';
}

current_user_can()函数会检查当前用户的$allcaps属性,判断其中是否包含指定的权限。

2.4 获取用户的角色权限:get_role_caps()

WP_User类的get_role_caps()方法负责根据用户的角色获取其权限。它会遍历用户所属的所有角色,并将这些角色的权限合并到用户的$caps属性中。

    /**
     * Gets the roles of the user.
     *
     * @since 2.0.0
     * @access public
     *
     * @return array Array of roles the user has.
     */
    public function get_roles() {
        return $this->roles;
    }

    /**
     * Gets all the capabilities of the user.
     *
     * @since 2.0.0
     * @access public
     *
     * @return array Array of all the capabilities that the user has.
     */
    public function get_caps() {
        return $this->caps;
    }

    /**
     * Gets all the capabilities of the user, including primitive and derived ones.
     *
     * @since 2.0.0
     * @access public
     *
     * @return array Array of all the capabilities that the user has.
     */
    public function get_allcaps() {
        return $this->allcaps;
    }

    /**
     * Sets the capabilities for the user.
     *
     * @since 2.1.0
     * @access public
     *
     * @uses WP_User::get_role_caps()
     *
     * @param bool $grant Whether the user is granted the capability.
     * @param string $cap Capability name.
     * @param mixed $args Optional further parameters, typically object ID.
     */
    public function add_cap( $cap, $grant = true, ...$args ) {
        $this->caps[ $cap ] = $grant;
        $this->allcaps[ $cap ] = $grant;

        if ( empty( $args ) ) {
            return;
        }

        $args = array_merge( array( $cap ), $args );
        /**
         * Fires after a user's capability is added.
         *
         * @since 3.1.0
         *
         * @param array   $args Array of arguments.
         * @param string  $cap  Capability name.
         * @param int     $id   The user ID.
         * @param WP_User $this Current WP_User object.
         */
        do_action( 'added_user_meta_cap', $args, $cap, $this->ID, $this );
    }

    /**
     * Removes a capability from the user.
     *
     * @since 2.1.0
     * @access public
     *
     * @param string $cap Capability name.
     */
    public function remove_cap( $cap ) {
        unset( $this->caps[ $cap ] );
        unset( $this->allcaps[ $cap ] );
    }

    /**
     * Returns whether the user has the specified capability.
     *
     * @since 2.0.0
     * @access public
     *
     * @param string $capability Capability name.
     * @param mixed ...$args Optional further parameters, typically object ID.
     * @return bool True if the user has the capability, false if not.
     */
    public function has_cap( $capability, ...$args ) {
        global $wp_roles;

        // Must have ALL specified capabilities.
        if ( is_array( $capability ) ) {
            $capabilities = $capability;
        } else {
            $capabilities = func_get_args();
        }

        $capabilities = array_map( 'strtolower', $capabilities );

        /**
         * Filters the user's capabilities.
         *
         * @since 2.0.0
         *
         * @param array   $allcaps An array of all the user's capabilities.
         * @param array   $caps    Array of required primitive capabilities.
         * @param array   $args    Array of the arguments passed to has_cap().
         * @param WP_User $this    Current WP_User object.
         */
        $allcaps = apply_filters( 'user_has_cap', $this->allcaps, $capabilities, $args, $this );

        // Grant the "super admin" capability if the user belongs to a super site.
        if ( is_multisite() && is_super_admin( $this->ID ) ) {
            $allcaps['manage_network'] = true;
            $allcaps['manage_sites']   = true;
            $allcaps['manage_network_users'] = true;
            $allcaps['manage_network_themes'] = true;
            $allcaps['manage_network_options'] = true;
        }

        $has_required_caps = true;
        foreach ( $capabilities as $capability ) {
            if ( ! isset( $allcaps[ $capability ] ) || ! $allcaps[ $capability ] ) {
                $has_required_caps = false;
                break;
            }
        }

        if ( ! $has_required_caps ) {
            return apply_filters( 'map_meta_cap', array( 'do_not_allow' ), $capability, $this->ID, $args );
        }

        return apply_filters( 'map_meta_cap', array(), $capability, $this->ID, $args );
    }

    /**
     * Sets the role capabilities.
     *
     * @since 2.0.0
     * @access public
     */
    public function get_role_caps() {
        global $wp_roles;

        $this->caps = apply_filters( 'user_caps', $this->caps, $this );
        $this->allcaps = array_merge( (array) $this->caps );

        if ( is_object( $wp_roles ) ) {
            foreach ( (array) $this->roles as $role ) {
                if ( isset( $wp_roles->role_objects[ $role ] ) ) {
                    $this->allcaps = array_merge( (array) $this->allcaps, (array) $wp_roles->role_objects[ $role ]->caps );
                }
            }
        }

        $this->allcaps = apply_filters( 'user_has_cap', $this->allcaps, array(), array(), $this );
    }

三、WP_User 的应用场景

WP_User 类在WordPress的开发中应用非常广泛,例如:

  • 用户认证: 在用户登录时,WordPress会创建一个WP_User 对象,用于验证用户的身份。
  • 权限控制: 在执行某些操作时,WordPress会检查当前用户是否拥有相应的权限,以确保安全性。
  • 用户数据展示: 在用户个人资料页面,WordPress会使用WP_User 对象来展示用户的个人信息。
  • 自定义开发: 在开发WordPress插件或主题时,你可以使用WP_User 类来获取用户信息,并根据用户的角色和权限执行不同的操作。

四、总结

WP_User 类是WordPress用户管理的核心。它封装了用户数据和权限信息,为WordPress的开发提供了强大的支持。理解WP_User 类的原理和使用方法,对于开发高质量的WordPress插件和主题至关重要。

希望今天的讲解对大家有所帮助!记住,理解源码,才能玩转WordPress!

发表回复

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