WordPress 评论查询:从 WP_Comment_Query
说起(讲座版)
大家好啊,各位观众老爷!今天咱们来聊聊 WordPress 里面一个相当重要的角色:WP_Comment_Query
。 别看名字长,其实它就是个专门负责找评论的家伙。不过,这找评论的门道可深了,它能根据各种奇奇怪怪的条件,把你想找的评论给你揪出来。
咱们今天就扒一扒 WP_Comment_Query
的源码,看看它到底是怎么构建那些复杂的查询条件的。 咱们争取把它讲的透彻,让大家以后在定制评论查询的时候,也能得心应手,不再发愁。
1. WP_Comment_Query
是个啥?
简单来说,WP_Comment_Query
是 WordPress 提供的一个类,专门用来查询评论。它封装了复杂的 SQL 查询逻辑,让你不用直接写 SQL 也能方便地获取评论。 想象一下,你要找所有未审核的评论,或者某个用户的所有评论,再或者某个文章的所有评论,用 WP_Comment_Query
都能轻松搞定。
2. 从构造函数开始:__construct()
咱们先从 WP_Comment_Query
的构造函数 __construct()
入手,看看它是怎么接受各种参数的。
public function __construct( $query = '' ) {
if ( ! empty( $query ) ) {
$this->query( $query );
}
}
这段代码很简单,就是判断一下有没有传入查询参数 $query
。 如果有,就调用 query()
方法来处理这些参数。 $query
可以是数组,也可以是查询字符串。 举个例子:
$args = array(
'number' => 10, // 获取 10 条评论
'status' => 'approve', // 只获取审核通过的评论
'post_id' => 123 // 只获取文章 ID 为 123 的评论
);
$comment_query = new WP_Comment_Query( $args );
或者,你也可以用查询字符串:
$comment_query = new WP_Comment_Query( 'number=10&status=approve&post_id=123' );
两种方式效果一样,看你喜欢哪个。
3. 核心方法:query()
query()
方法才是真正干活的。 它负责解析查询参数,构建 SQL 查询语句,然后执行查询。
public function query( $query ) {
global $wpdb;
$this->query_vars = wp_parse_args( $query, $this->query_vars_defaults );
$this->query_vars = $this->sanitize_query( $this->query_vars );
extract( $this->query_vars, EXTR_SKIP );
$this->comment_fields = '*';
if ( 'ids' == $fields ) {
$this->comment_fields = 'comment_ID';
}
$this->sql_clauses = $this->get_sql_clauses();
$this->comments = $wpdb->get_results( $this->sql_clauses['select'] . $this->sql_clauses['from'] . $this->sql_clauses['where'] . $this->sql_clauses['orderby'] . $this->sql_clauses['limits'] );
if ( $this->comments ) {
wp_cache_add_multiple( $this->comments, 'comments' );
//... (省略部分代码,关于 populate_comments 等)
}
return $this->comments;
}
咱们一步一步来分析:
wp_parse_args()
: 这个函数把传入的查询参数$query
和默认参数$this->query_vars_defaults
合并。 默认参数定义了很多默认的查询选项,比如排序方式、评论状态等等。sanitize_query()
: 这个函数负责对查询参数进行安全过滤,防止 SQL 注入。extract()
: 这个函数把$this->query_vars
数组里的键值对提取成变量。 比如,$this->query_vars['number']
就会变成$number
变量。get_sql_clauses()
: 这个方法是重点,它负责构建 SQL 查询语句的各个部分,包括SELECT
、FROM
、WHERE
、ORDER BY
和LIMIT
子句。$wpdb->get_results()
: 这个函数执行 SQL 查询,获取结果。wp_cache_add_multiple()
: 这个函数把查询结果缓存起来,下次再查同样的评论就不用再查数据库了,提高性能。
4. SQL 构建的关键:get_sql_clauses()
get_sql_clauses()
方法是 WP_Comment_Query
的灵魂。 它根据查询参数,动态地构建 SQL 查询语句的各个部分。 咱们来看看这个方法的简化版:
protected function get_sql_clauses() {
global $wpdb;
$sql = array();
$where = "WHERE 1=1"; // 默认条件,总是成立
// 处理 comment__in 参数
if ( ! empty( $this->query_vars['comment__in'] ) ) {
$ids = wp_parse_id_list( $this->query_vars['comment__in'] );
$where .= " AND comment_ID IN (" . implode( ',', array_map( 'intval', $ids ) ) . ")";
}
// 处理 comment__not_in 参数
if ( ! empty( $this->query_vars['comment__not_in'] ) ) {
$ids = wp_parse_id_list( $this->query_vars['comment__not_in'] );
$where .= " AND comment_ID NOT IN (" . implode( ',', array_map( 'intval', $ids ) ) . ")";
}
// 处理 post_id 参数
if ( ! empty( $this->query_vars['post_id'] ) ) {
$post_ids = wp_parse_id_list( $this->query_vars['post_id'] );
$where .= " AND comment_post_ID IN (" . implode( ',', array_map( 'intval', $post_ids ) ) . ")";
}
// 处理 status 参数
if ( ! empty( $this->query_vars['status'] ) ) {
$statuses = $this->query_vars['status'];
if ( is_string( $statuses ) ) {
$statuses = explode( ',', $statuses );
}
$status_clauses = array();
foreach ( $statuses as $status ) {
$status = trim( $status );
switch ( $status ) {
case 'hold':
case 'unapproved':
$status_clauses[] = "comment_approved = '0'";
break;
case 'approve':
case 'approved':
$status_clauses[] = "comment_approved = '1'";
break;
case 'spam':
$status_clauses[] = "comment_approved = 'spam'";
break;
case 'trash':
$status_clauses[] = "comment_approved = 'trash'";
break;
default:
$status_clauses[] = "comment_approved = '" . esc_sql( $status ) . "'";
break;
}
}
if ( ! empty( $status_clauses ) ) {
$where .= " AND (" . implode( ' OR ', $status_clauses ) . ")";
}
}
// 处理 number 和 offset 参数
$number = absint( $this->query_vars['number'] );
$offset = absint( $this->query_vars['offset'] );
if ( $number ) {
if ( $offset ) {
$limits = 'LIMIT ' . $offset . ',' . $number;
} else {
$limits = 'LIMIT ' . $number;
}
} else {
$limits = '';
}
$sql['select'] = "SELECT {$this->comment_fields}";
$sql['from'] = " FROM {$wpdb->comments}";
$sql['where'] = $where;
$sql['orderby'] = $this->get_comment_order_by_clause();
$sql['limits'] = $limits;
return $sql;
}
这个方法的核心逻辑是,根据不同的查询参数,拼接 WHERE
子句。 比如,如果指定了 post_id
,就拼接 AND comment_post_ID IN (...)
。 如果指定了 status
,就拼接 AND comment_approved = ...
。
get_sql_clauses
里面还有很多其他的参数处理,比如 date_query
(日期查询), author__in
, author__not_in
等等, 这里就不一一列举了, 核心思想都是一样的: 根据查询参数,拼接 SQL 语句。
5. 排序的处理:get_comment_order_by_clause()
get_comment_order_by_clause()
方法负责构建 ORDER BY
子句。 它可以根据 orderby
和 order
参数,指定评论的排序方式。
protected function get_comment_order_by_clause() {
global $wpdb;
$orderby = $this->query_vars['orderby'];
$order = $this->query_vars['order'];
$allowed_keys = array(
'comment_ID',
'comment_author',
'comment_date',
'comment_content',
'comment_karma',
'comment_approved',
'comment_post_ID',
'comment_parent',
'comment_type',
'comment__in',
);
if ( ! in_array( $orderby, $allowed_keys, true ) ) {
$orderby = 'comment_date'; // 默认按日期排序
}
$order = strtoupper( $order );
if ( 'DESC' !== $order && 'ASC' !== $order ) {
$order = 'DESC'; // 默认降序
}
return "ORDER BY {$orderby} {$order}";
}
这个方法首先检查 orderby
参数是否合法,如果不合法,就使用默认的 comment_date
排序。 然后,它检查 order
参数是否是 ASC
或 DESC
,如果不是,就使用默认的 DESC
降序。 最后,它拼接 ORDER BY
子句。
6. 举个栗子:复杂查询
咱们来举个例子,看看怎么用 WP_Comment_Query
构建一个复杂的查询:
$args = array(
'number' => 20, // 获取 20 条评论
'status' => 'approve', // 只获取审核通过的评论
'post_id' => array(123, 456), // 获取文章 ID 为 123 和 456 的评论
'date_query' => array(
array(
'year' => 2023,
'month' => 10,
),
), // 只获取 2023 年 10 月的评论
'orderby' => 'comment_date', // 按日期排序
'order' => 'ASC', // 升序
);
$comment_query = new WP_Comment_Query( $args );
$comments = $comment_query->get_comments();
if ( $comments ) {
foreach ( $comments as $comment ) {
echo '<p>' . $comment->comment_content . '</p>';
}
} else {
echo '没有找到评论';
}
这段代码会获取 2023 年 10 月,文章 ID 为 123 和 456 的,审核通过的 20 条评论,并按照日期升序排列。
7. 总结
WP_Comment_Query
是 WordPress 提供的一个强大的评论查询工具。 它通过封装复杂的 SQL 查询逻辑,让你不用直接写 SQL 也能方便地获取评论。 核心思想是:
- 接收查询参数。
- 对查询参数进行安全过滤。
- 根据查询参数,动态地构建 SQL 查询语句的各个部分,包括
SELECT
、FROM
、WHERE
、ORDER BY
和LIMIT
子句。 - 执行 SQL 查询,获取结果。
- 缓存查询结果,提高性能。
通过理解 WP_Comment_Query
的源码,你可以更好地定制评论查询,满足各种奇奇怪怪的需求。 希望今天的讲座对大家有所帮助。 谢谢大家!
8. 常用参数列表
为了方便大家查阅,我整理了一个 WP_Comment_Query
常用参数的表格:
参数名 | 类型 | 描述 |
---|---|---|
number |
int |
要获取的评论数量。 |
offset |
int |
偏移量,从第几条评论开始获取。 |
orderby |
string |
排序字段,可选值包括 comment_ID , comment_author , comment_date , comment_content , comment_karma , comment_approved , comment_post_ID , comment_parent , comment_type 等。 |
order |
string |
排序方式,可选值包括 ASC (升序) 和 DESC (降序)。 |
status |
string | array |
评论状态,可选值包括 approve , hold , spam , trash 。 可以是单个状态,也可以是状态数组。 |
post_id |
int | array |
文章 ID,只获取指定文章的评论。 可以是单个 ID,也可以是 ID 数组。 |
post_author |
int | array |
文章作者 ID,只获取指定作者的文章的评论。可以是单个 ID,也可以是 ID 数组。 |
post_type |
string | array |
文章类型,只获取指定文章类型的评论。 可以是单个类型,也可以是类型数组。 |
post_status |
string | array |
文章状态,只获取指定文章状态的评论。 可以是单个状态,也可以是状态数组。 |
comment__in |
array |
只获取指定评论 ID 的评论。 |
comment__not_in |
array |
排除指定评论 ID 的评论。 |
author_email |
string |
评论作者邮箱。 |
author__in |
array |
只获取指定评论作者 ID 的评论。 |
author__not_in |
array |
排除指定评论作者 ID 的评论。 |
date_query |
array |
日期查询,可以根据年份、月份、日期等条件查询评论。 具体用法参考 WordPress 官方文档。 |
search |
string |
搜索评论内容。 |
fields |
string |
返回字段,可选值包括 'all' (返回所有字段) 和 'ids' (只返回评论 ID)。 |
meta_query |
array |
元数据查询,可以根据评论的元数据查询评论。 具体用法参考 WordPress 官方文档。 |
这个表格列出了 WP_Comment_Query
中常用的参数,希望对大家有所帮助。 在实际使用中,可以根据自己的需求选择合适的参数,构建出满足需求的评论查询。