好的,下面是一篇关于利用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 钩子允许我们动态修改查询参数。合理利用这些工具,可以构建高度定制化的用户管理系统,满足各种复杂的业务需求。