各位观众老爷们,大家好!我是今天的主讲人,咱们今天就来聊聊WordPress里那个神秘又强大的 WP_Comment_Query
类,看看它到底是怎么构建评论查询的。准备好了吗?那咱们就开始吧!
一、 什么是 WP_Comment_Query
?
简单来说,WP_Comment_Query
就是 WordPress 提供的一个专门用来查询评论的类。你可能觉得直接用 get_comments()
函数就行了,但 WP_Comment_Query
更加灵活,可以让你更精细地控制评论查询的条件和结果。它封装了复杂的 SQL 查询逻辑,让你不用直接写 SQL 语句就能搞定各种评论查询需求。
二、WP_Comment_Query
的构造函数:一切的起点
我们先从 WP_Comment_Query
类的构造函数入手,看看它都做了些什么:
/**
* Constructor.
*
* @param string|array $query Optional. Array or string of Query parameters. See {@see WP_Comment_Query::parse_query()}
* for information on accepted arguments.
*/
public function __construct( $query = '' ) {
$this->query = wp_parse_args( $query ); // 将传入的查询参数转换为数组
$this->query_vars_hash = md5( serialize( $this->query ) ); // 生成查询参数的哈希值,用于缓存
$this->parse_query( $this->query ); // 解析查询参数
$this->get_comments(); // 执行查询
}
这段代码看起来是不是很简单?但它做了三件重要的事情:
-
wp_parse_args()
:参数标准化wp_parse_args()
函数的作用是将传入的查询参数(可以是字符串或数组)转换为一个标准的数组。如果传入的是字符串,它会尝试将其解析为键值对。这样做的目的是为了方便后续的参数处理。$defaults = array( 'number' => '20', 'offset' => '0', 'orderby' => 'comment_date', 'order' => 'DESC', // ... 其他默认参数 ); $this->query = wp_parse_args( $query, $defaults );
wp_parse_args()
会将用户传入的参数与默认参数合并,确保所有必要的参数都有值。 -
md5(serialize())
:生成查询哈希值为什么要生成查询参数的哈希值呢?答案是:为了缓存!WordPress 会根据这个哈希值来判断是否已经执行过相同的查询,如果已经执行过,就可以直接从缓存中获取结果,避免重复查询数据库,提高性能。
-
parse_query()
:解析查询参数这是最关键的一步,
parse_query()
函数负责解析查询参数,并将它们转换为 SQL 查询语句中使用的条件。 -
get_comments()
:执行查询根据解析后的查询参数,执行SQL语句,获取评论数据。
三、parse_query()
:SQL 构建的核心
parse_query()
函数是 WP_Comment_Query
类的核心,它负责将查询参数转换为 SQL 查询语句。让我们深入了解一下它的工作原理。
/**
* Parse arguments passed to the comment query with wp_parse_args() and fill
* unavailable query parameters.
*
* @param string|array $query Array of query parameters.
*/
public function parse_query( $query = '' ) {
// 1. 初始化查询变量
$this->query_vars = wp_parse_args( $query, $this->query_vars );
// 2. 处理各种查询参数
$this->comment__in = wp_parse_id_list( $this->query_vars['comment__in'] );
$this->comment__not_in = wp_parse_id_list( $this->query_vars['comment__not_in'] );
$this->hierarchical = $this->query_vars['hierarchical'];
$this->number = absint( $this->query_vars['number'] );
$this->offset = absint( $this->query_vars['offset'] );
$this->paged = absint( $this->query_vars['paged'] );
$this->count = (bool) $this->query_vars['count'];
$this->no_found_rows = (bool) $this->query_vars['no_found_rows'];
$this->orderby = $this->query_vars['orderby'];
$this->order = $this->query_vars['order'];
$this->search = $this->query_vars['search'];
$this->status = $this->query_vars['status'];
$this->approve = $this->query_vars['approve'];
$this->author__in = wp_parse_id_list( $this->query_vars['author__in'] );
$this->author__not_in = wp_parse_id_list( $this->query_vars['author__not_in'] );
$this->post_id = absint( $this->query_vars['post_id'] );
$this->post__in = wp_parse_id_list( $this->query_vars['post__in'] );
$this->post__not_in = wp_parse_id_list( $this->query_vars['post__not_in'] );
$this->parent = $this->query_vars['parent'];
$this->parent__in = wp_parse_id_list( $this->query_vars['parent__in'] );
$this->parent__not_in = wp_parse_id_list( $this->query_vars['parent__not_in'] );
$this->fields = $this->query_vars['fields'];
$this->name = $this->query_vars['name'];
$this->email = $this->query_vars['email'];
$this->url = $this->query_vars['url'];
$this->comment_author = $this->query_vars['comment_author'];
$this->comment_author_email = $this->query_vars['comment_author_email'];
$this->comment_author_url = $this->query_vars['comment_author_url'];
$this->comment_author_IP = $this->query_vars['comment_author_IP'];
$this->date_query = $this->query_vars['date_query'];
$this->meta_query = $this->query_vars['meta_query'];
$this->type = $this->query_vars['type'];
$this->type__in = $this->query_vars['type__in'];
$this->type__not_in = $this->query_vars['type__not_in'];
$this->include_unapproved = $this->query_vars['include_unapproved'];
$this->user_id = $this->query_vars['user_id'];
$this->callback = $this->query_vars['callback'];
$this->walker = $this->query_vars['walker'];
// 3. 过滤查询参数
$this->query_vars = apply_filters( 'comments_clauses', $this->query_vars, $this );
$this->query_vars = apply_filters( 'comments_clauses_request', $this->query_vars, $this );
}
这个函数的主要工作是:
- 初始化查询变量: 将传入的参数与默认参数合并,确保所有必要的参数都有值。
- 处理各种查询参数: 对各种查询参数进行处理,例如将
comment__in
参数转换为整数数组,将number
参数转换为整数等等。 - 过滤查询参数: 使用
apply_filters()
函数对查询参数进行过滤,允许其他插件或主题修改查询参数。
四、get_comments()
:构建 SQL 查询语句并执行
get_comments()
函数是 WP_Comment_Query
类中真正执行查询的地方。它会根据解析后的查询参数构建 SQL 查询语句,并执行该语句,然后返回查询结果。
/**
* Retrieve comments matching the current query vars.
*
* @since 3.1.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @return array|int List of comments, or number of comments when 'count' is passed as a query var.
*/
public function get_comments() {
global $wpdb;
$comments = array();
/**
* Fires before comments query is run.
*
* @since 5.1.0
*
* @param WP_Comment_Query $this The WP_Comment_Query instance (passed by reference).
*/
do_action_ref_array( 'pre_get_comments', array( &$this ) );
/**
* Filters the comments query clauses.
*
* @since 3.1.0
*
* @param array $clauses Empty array.
* @param WP_Comment_Query $this The WP_Comment_Query instance (passed by reference).
*/
$clauses = apply_filters_ref_array( 'comments_clauses', array( array(), &$this ) );
$where = ! empty( $clauses['where'] ) ? 'WHERE 1=1 ' . $clauses['where'] : '';
$join = ! empty( $clauses['join'] ) ? $clauses['join'] : '';
$orderby = ! empty( $clauses['orderby'] ) ? 'ORDER BY ' . $clauses['orderby'] : '';
$limits = ! empty( $clauses['limits'] ) ? 'LIMIT ' . $clauses['limits'] : '';
$fields = isset( $clauses['fields'] ) ? $clauses['fields'] : '*';
$this->sql_clauses = compact( 'fields', 'join', 'where', 'orderby', 'limits' );
if ( $this->count ) {
$found_comments = (int) $wpdb->get_var( "SELECT COUNT( DISTINCT {$wpdb->comments}.comment_ID ) FROM {$wpdb->comments} {$join} {$where}" );
/**
* Filters the found comments query.
*
* @since 3.1.0
*
* @param string $found_comments_query The complete COUNT query.
* @param WP_Comment_Query $this The WP_Comment_Query instance (passed by reference).
*/
$found_comments_query = apply_filters( 'found_comments_query', "SELECT COUNT( DISTINCT {$wpdb->comments}.comment_ID ) FROM {$wpdb->comments} {$join} {$where}", $this );
/**
* Filters the total number of found comments for the query.
*
* @since 3.1.0
*
* @param int $found_comments The total number of comments found.
* @param WP_Comment_Query $this The WP_Comment_Query instance (passed by reference).
*/
return apply_filters( 'found_comments', $found_comments, $this );
}
$this->request = "SELECT {$fields} FROM {$wpdb->comments} {$join} {$where} {$orderby} {$limits}";
$comments = $wpdb->get_results( $this->request );
return $comments;
}
这个函数的主要步骤如下:
- 构建 SQL 查询语句: 根据解析后的查询参数,构建 SQL 查询语句的各个部分,例如
WHERE
子句、JOIN
子句、ORDER BY
子句和LIMIT
子句等等。 - 执行 SQL 查询语句: 使用
$wpdb->get_results()
函数执行 SQL 查询语句,并获取查询结果。 - 返回查询结果: 将查询结果封装成一个数组,并返回该数组。
五、WP_Comment_Query
的核心参数
WP_Comment_Query
支持很多查询参数,下面列出一些常用的参数:
参数 | 类型 | 描述 |
---|---|---|
comment__in |
array | 只获取指定 ID 的评论。 |
comment__not_in |
array | 排除指定 ID 的评论。 |
number |
int | 获取的评论数量。 |
offset |
int | 偏移量,用于分页。 |
orderby |
string | 排序字段,例如 comment_date 、comment_ID 等。 |
order |
string | 排序方式,ASC (升序)或 DESC (降序)。 |
status |
string | 评论状态,approve (已审核)、hold (待审核)、spam (垃圾评论)等。 |
post_id |
int | 只获取指定文章的评论。 |
post__in |
array | 只获取指定文章 ID 列表的评论。 |
post__not_in |
array | 排除指定文章 ID 列表的评论。 |
author__in |
array | 只获取指定作者 ID 列表的评论。 |
author__not_in |
array | 排除指定作者 ID 列表的评论。 |
date_query |
array | 日期查询参数,可以根据日期范围过滤评论。 |
meta_query |
array | 元数据查询参数,可以根据评论元数据过滤评论。 |
type |
string | 评论类型,例如 comment 、trackback 、pingback 等。 |
type__in |
array | 只获取指定评论类型列表的评论。 |
type__not_in |
array | 排除指定评论类型列表的评论。 |
search |
string | 搜索评论内容。 |
六、使用 WP_Comment_Query
的例子
说了这么多,不如来几个实际的例子,让你更直观地了解 WP_Comment_Query
的用法。
例子 1:获取指定文章的最新 10 条评论
$args = array(
'post_id' => 123, // 文章 ID
'number' => 10,
'orderby' => 'comment_date',
'order' => 'DESC',
);
$comments_query = new WP_Comment_Query( $args );
$comments = $comments_query->get_comments();
if ( $comments ) {
foreach ( $comments as $comment ) {
echo '<p>' . $comment->comment_content . '</p>';
}
} else {
echo 'No comments found.';
}
例子 2:获取所有待审核的评论
$args = array(
'status' => 'hold', // 待审核
);
$comments_query = new WP_Comment_Query( $args );
$comments = $comments_query->get_comments();
if ( $comments ) {
foreach ( $comments as $comment ) {
echo '<p>' . $comment->comment_content . '</p>';
}
} else {
echo 'No comments found.';
}
例子 3:使用 date_query
获取指定日期范围的评论
$args = array(
'date_query' => array(
array(
'after' => '2023-01-01',
'before' => '2023-01-31',
'inclusive' => true, // 包含开始和结束日期
),
),
);
$comments_query = new WP_Comment_Query( $args );
$comments = $comments_query->get_comments();
if ( $comments ) {
foreach ( $comments as $comment ) {
echo '<p>' . $comment->comment_content . '</p>';
}
} else {
echo 'No comments found.';
}
例子 4:使用 meta_query
获取指定元数据的评论
$args = array(
'meta_query' => array(
array(
'key' => 'rating',
'value' => '5',
'compare' => '=',
'type' => 'NUMERIC',
),
),
);
$comments_query = new WP_Comment_Query( $args );
$comments = $comments_query->get_comments();
if ( $comments ) {
foreach ( $comments as $comment ) {
echo '<p>' . $comment->comment_content . '</p>';
}
} else {
echo 'No comments found.';
}
七、WP_Comment_Query
与 get_comments()
的区别
你可能会问,既然有了 WP_Comment_Query
,那 get_comments()
还有什么用呢?
其实 get_comments()
函数内部也是使用 WP_Comment_Query
类来实现的。get_comments()
函数是一个更简单的封装,它接受一个参数数组,然后将其传递给 WP_Comment_Query
类的构造函数。
WP_Comment_Query
更加灵活,可以直接访问其属性和方法,可以更精细地控制查询过程。如果你需要更复杂的评论查询需求,建议使用 WP_Comment_Query
类。
八、总结
WP_Comment_Query
类是 WordPress 提供的一个强大而灵活的评论查询工具。通过深入理解它的源码和参数,你可以轻松地构建各种复杂的评论查询需求。
希望今天的讲座能帮助你更好地理解 WP_Comment_Query
类。如果你还有任何问题,欢迎提问!感谢大家的收听!下次再见!