好的,下面是一篇关于利用WP_User_Query
和pre_user_query
钩子进行自定义用户查询的技术文章,以讲座模式呈现。
WordPress 用户查询进阶:WP_User_Query
与 pre_user_query
大家好!今天我们来深入探讨 WordPress 中用户查询的强大工具:WP_User_Query
类以及 pre_user_query
钩子。掌握它们,你就能构建高度定制化的用户列表,满足各种复杂的业务需求。
WP_User_Query
: 灵活的用户检索利器
WP_User_Query
是 WordPress 提供的一个类,用于执行自定义的用户查询。相比直接使用 $wpdb
操作数据库,它提供了更安全、更便捷的方式来获取用户数据。
基本用法:
最简单的用法是实例化 WP_User_Query
类,并传入一个参数数组。
$args = array(
'role' => 'subscriber', // 只查询订阅者角色
);
$user_query = new WP_User_Query( $args );
if ( ! empty( $user_query->get_results() ) ) {
foreach ( $user_query->get_results() as $user ) {
echo '用户名: ' . $user->user_login . '<br>';
}
} else {
echo '没有找到用户。';
}
这段代码会查询所有角色为 subscriber
的用户,并输出他们的用户名。
更丰富的参数:
WP_User_Query
支持大量参数,可以让你精确控制查询条件。下面是一些常用的参数:
参数名 | 类型 | 描述 | 示例 |
---|---|---|---|
role |
string | 只查询指定角色的用户。 | 'administrator' , 'editor' , 'author' , 'contributor' , 'subscriber' |
role__in |
array | 查询属于多个指定角色的用户。 | array( 'administrator', 'editor' ) |
role__not_in |
array | 排除指定角色的用户。 | array( 'subscriber' ) |
include |
array | 只查询指定 ID 的用户。 | array( 1, 2, 3 ) |
exclude |
array | 排除指定 ID 的用户。 | array( 4, 5, 6 ) |
search |
string | 搜索用户名、昵称、邮箱地址。 | 'john' |
search_columns |
array | 指定搜索的列。默认是 array( 'user_login', 'user_email', 'user_url', 'user_nicename' ) |
array( 'user_login', 'user_email' ) |
orderby |
string | 排序字段。 | 'ID' , 'login' , 'nicename' , 'email' , 'url' , 'registered' , 'post_count' |
order |
string | 排序方式。 | 'ASC' , 'DESC' |
number |
int | 返回的用户数量。 | 10 |
offset |
int | 偏移量,用于分页。 | 20 |
meta_key |
string | 查询指定用户元数据的用户。 | 'age' |
meta_value |
mixed | meta_key 对应的元数据值。 |
'30' |
meta_compare |
string | 元数据值的比较方式。 | '=' , '!=' , '>' , '>=' , '<' , '<=' , 'LIKE' , 'NOT LIKE' , 'IN' , 'NOT IN' , 'BETWEEN' , 'NOT BETWEEN' , 'EXISTS' , 'NOT EXISTS' |
meta_query |
array | 更复杂的元数据查询,可以组合多个元数据条件。 | 见下文详细解释 |
date_query |
array | 日期查询,例如查询注册时间在某个范围内的用户。 | 见下文详细解释 |
fields |
string | 返回的字段。'ID' 只返回用户 ID,'all_with_meta' 返回所有用户数据和元数据。 |
'ID' , 'all' , 'all_with_meta' |
has_published_posts |
mixed | 根据用户是否发布过文章进行筛选。可以传递post type或者一个post type数组 | true , false , 'post' , array('post','page') |
元数据查询 (meta_query
):
meta_query
允许你根据用户元数据进行更复杂的查询。它是一个数组,可以包含多个元数据条件。
$args = array(
'meta_query' => array(
'relation' => 'AND', // 多个条件之间的关系,可以是 'AND' 或 'OR'
array(
'key' => 'age',
'value' => '30',
'compare' => '=',
'type' => 'NUMERIC', // 指定元数据类型
),
array(
'key' => 'city',
'value' => 'New York',
'compare' => 'LIKE',
),
),
);
$user_query = new WP_User_Query( $args );
这段代码会查询所有年龄为 30 岁且居住城市包含 "New York" 的用户。'type'
参数用于指定元数据类型,可以是 'NUMERIC'
, 'CHAR'
, 'DATE'
, 'DATETIME'
, 'BINARY'
, 'SIGNED'
, 'UNSIGNED'
。
日期查询 (date_query
):
date_query
允许你根据用户的注册日期进行查询。
$args = array(
'date_query' => array(
array(
'year' => 2023,
'month' => 10,
),
array(
'after' => '2023-01-01',
'before' => '2023-12-31',
'inclusive' => true, // 是否包含开始和结束日期
),
),
);
$user_query = new WP_User_Query( $args );
这段代码会查询所有 2023 年 10 月注册的用户,以及所有在 2023 年注册的用户。
获取查询结果:
WP_User_Query
提供了几个方法来获取查询结果:
get_results()
: 返回一个WP_User
对象数组。get_total()
: 返回符合条件的用户总数。get_users()
: 返回用户 ID 数组(如果fields参数设置为’ID’) 或者 WP_User对象数组(如果fields参数设置为’all’, 或者省略)。
$user_query = new WP_User_Query( $args );
$users = $user_query->get_results();
$total_users = $user_query->get_total();
echo '总共有 ' . $total_users . ' 个符合条件的用户。<br>';
foreach ( $users as $user ) {
echo '用户名: ' . $user->user_login . '<br>';
}
pre_user_query
: 拦截并修改查询
pre_user_query
钩子允许你在 WP_User_Query
执行 SQL 查询之前拦截并修改查询参数。这为你提供了极大的灵活性,可以根据你的需求动态调整查询条件。
基本用法:
add_action( 'pre_user_query', 'my_custom_user_query' );
function my_custom_user_query( $query ) {
// 修改 $query 对象
if ( is_admin() && isset( $_GET['custom_filter'] ) && $_GET['custom_filter'] == 'true' ) {
$meta_query = array(
array(
'key' => 'custom_field',
'value' => 'custom_value',
'compare' => '=',
),
);
$query->set( 'meta_query', $meta_query );
}
}
这段代码会在后台管理页面,当 URL 中包含 custom_filter=true
参数时,添加一个额外的元数据查询条件。
$query
对象:
传递给钩子函数的 $query
对象是 WP_User_Query
的实例。你可以使用它的 set()
方法来修改查询参数。
$query->set( 'role', 'editor' );
$query->set( 'orderby', 'registered' );
$query->set( 'order', 'ASC' );
条件判断:
在钩子函数中,你通常需要进行一些条件判断,以确定是否需要修改查询。常用的判断条件包括:
is_admin()
: 判断是否在后台管理页面。is_user_logged_in()
: 判断用户是否已登录。get_current_user_id()
: 获取当前用户的 ID。$_GET
或$_POST
: 获取 URL 参数或表单数据。
优先级:
你可以通过 add_action()
函数的第三个参数来指定钩子函数的优先级。优先级越低,钩子函数执行得越早。
add_action( 'pre_user_query', 'my_custom_user_query', 10 ); // 默认优先级是 10
实例:根据用户自定义字段排序
假设你想根据用户自定义字段 age
进行排序。WP_User_Query
本身不支持直接按元数据排序,但你可以使用 pre_user_query
钩子来实现。
add_action( 'pre_user_query', 'my_custom_user_age_orderby' );
function my_custom_user_age_orderby( $query ) {
if ( isset( $query->query_vars['orderby'] ) && $query->query_vars['orderby'] == 'age' ) {
global $wpdb;
$query->query_from .= " LEFT JOIN {$wpdb->usermeta} AS um ON {$wpdb->users}.ID = um.user_id AND um.meta_key = 'age'";
$query->query_orderby = "ORDER BY CAST(um.meta_value AS SIGNED) " . ( isset( $query->query_vars['order'] ) ? $query->query_vars['order'] : 'ASC' );
}
}
这段代码做了以下几件事:
- 检查
orderby
参数: 首先,它检查WP_User_Query
的orderby
参数是否设置为age
。如果是,则执行后续操作。 - 连接
usermeta
表: 它使用LEFT JOIN
将wp_users
表和wp_usermeta
表连接起来,连接条件是user_id
等于wp_users
表的ID
,并且meta_key
等于'age'
。 - 修改
orderby
子句: 它将orderby
子句修改为ORDER BY CAST(um.meta_value AS SIGNED) ASC
。CAST(um.meta_value AS SIGNED)
用于将元数据值转换为数字类型,以便进行正确的排序。ASC
表示升序排列,如果需要降序排列,可以将ASC
修改为DESC
。
现在,你可以在 WP_User_Query
中使用 orderby
参数来按 age
排序了:
$args = array(
'orderby' => 'age',
'order' => 'DESC', // 降序排列
);
$user_query = new WP_User_Query( $args );
更复杂的例子:根据用户角色和自定义字段进行筛选和排序
假设你的网站有不同的用户角色,并且每个用户都有一个自定义字段 membership_level
(例如: ‘basic’, ‘premium’, ‘vip’)。 你想创建一个用户列表,可以根据用户角色和 membership_level
进行筛选和排序。
前端筛选表单:
首先,你需要创建一个前端表单,允许用户选择角色和排序方式。
<form id="user-filter-form" method="GET">
<label for="role">角色:</label>
<select name="role" id="role">
<option value="">所有角色</option>
<option value="subscriber">订阅者</option>
<option value="editor">编辑</option>
<option value="author">作者</option>
<option value="administrator">管理员</option>
</select>
<label for="orderby">排序方式:</label>
<select name="orderby" id="orderby">
<option value="login">用户名</option>
<option value="membership_level">会员等级</option>
</select>
<label for="order">排序:</label>
<select name="order" id="order">
<option value="ASC">升序</option>
<option value="DESC">降序</option>
</select>
<input type="submit" value="筛选">
</form>
<div id="user-list">
<!-- 用户列表将在这里显示 -->
</div>
<script>
// 使用 JavaScript/jQuery 处理表单提交和 AJAX 请求
jQuery(document).ready(function($) {
$('#user-filter-form').submit(function(e) {
e.preventDefault(); // 阻止默认表单提交
var formData = $(this).serialize(); // 获取表单数据
$.ajax({
url: ajaxurl, // WordPress AJAX URL
type: 'GET',
data: formData + '&action=filter_users', // 添加 action 参数
success: function(response) {
$('#user-list').html(response); // 更新用户列表
}
});
});
});
</script>
后端处理 AJAX 请求:
接下来,你需要创建一个 PHP 函数来处理 AJAX 请求,并使用 WP_User_Query
来查询用户。
add_action( 'wp_ajax_filter_users', 'filter_users_callback' );
add_action( 'wp_ajax_nopriv_filter_users', 'filter_users_callback' ); // 允许未登录用户访问
function filter_users_callback() {
$args = array();
// 获取表单数据
$role = isset( $_GET['role'] ) ? sanitize_text_field( $_GET['role'] ) : '';
$orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'login';
$order = isset( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'ASC';
// 设置查询参数
if ( ! empty( $role ) ) {
$args['role'] = $role;
}
$args['orderby'] = $orderby;
$args['order'] = $order;
// 创建 WP_User_Query 对象
$user_query = new WP_User_Query( $args );
// 输出用户列表
if ( ! empty( $user_query->get_results() ) ) {
echo '<ul>';
foreach ( $user_query->get_results() as $user ) {
echo '<li>用户名: ' . $user->user_login . ', 会员等级: ' . get_user_meta( $user->ID, 'membership_level', true ) . '</li>';
}
echo '</ul>';
} else {
echo '没有找到用户。';
}
wp_die(); // 结束 AJAX 请求
}
使用 pre_user_query
钩子进行自定义排序:
最后,你需要使用 pre_user_query
钩子来处理按 membership_level
排序的情况。
add_action( 'pre_user_query', 'my_custom_membership_level_orderby' );
function my_custom_membership_level_orderby( $query ) {
if ( isset( $query->query_vars['orderby'] ) && $query->query_vars['orderby'] == 'membership_level' ) {
global $wpdb;
$query->query_from .= " LEFT JOIN {$wpdb->usermeta} AS um ON {$wpdb->users}.ID = um.user_id AND um.meta_key = 'membership_level'";
$query->query_orderby = "ORDER BY um.meta_value " . ( isset( $query->query_vars['order'] ) ? $query->query_vars['order'] : 'ASC' );
}
}
现在,你可以通过前端表单选择用户角色和排序方式,并动态更新用户列表。
安全注意事项:
- 数据验证和清理: 始终对用户输入的数据进行验证和清理,以防止 SQL 注入等安全问题。 使用
sanitize_text_field()
等函数来清理用户输入。 - 权限控制: 确保只有授权用户才能访问用户数据。 使用 WordPress 的权限系统来控制用户访问权限。
- 避免过度使用: 过度使用
pre_user_query
钩子可能会影响性能。 只在必要时才使用它,并尽量优化你的代码。
总结
今天我们学习了 WP_User_Query
类的强大功能,它能让你以安全便捷的方式进行用户查询。同时,pre_user_query
钩子则提供了更高级的自定义选项,允许你在查询执行前修改查询参数,实现各种复杂的业务逻辑。掌握这些工具,你就能在 WordPress 中构建高度定制化的用户管理系统。
一些思考
WP_User_Query
提供了一种安全便捷的方式来查询用户,pre_user_query
钩子允许我们动态修改查询参数。合理利用这些工具,可以构建高度定制化的用户管理系统,满足各种复杂的业务需求。