大家好,今天咱们来聊聊WordPress评论系统里两个重要的角色:WP_Comment
和WP_Comment_Query
。别被这些名字吓跑,其实它们就像一对好基友,一个负责评论的数据,一个负责把评论找出来。
一、WP_Comment
:评论数据的容器
WP_Comment
类,顾名思义,就是用来封装一条评论数据的。它就像一个精心设计的盒子,把评论的各种信息都装在里面,方便我们使用。
1.1 类的定义和属性
首先,我们来看看WP_Comment
类的基本结构(简化版):
/**
* Core class used to implement the WP_Comment object.
*
* @since 4.4.0
*/
class WP_Comment {
/**
* Comment ID.
*
* @since 4.4.0
* @var int
*/
public $comment_ID = 0;
/**
* Comment post ID.
*
* @since 4.4.0
* @var int
*/
public $comment_post_ID = 0;
/**
* Comment author name.
*
* @since 4.4.0
* @var string
*/
public $comment_author = '';
/**
* Comment author email address.
*
* @since 4.4.0
* @var string
*/
public $comment_author_email = '';
/**
* Comment author URL.
*
* @since 4.4.0
* @var string
*/
public $comment_author_url = '';
/**
* Comment author IP address.
*
* @since 4.4.0
* @var string
*/
public $comment_author_IP = '';
/**
* Comment date and time (Y-m-d H:i:s).
*
* @since 4.4.0
* @var string
*/
public $comment_date = '0000-00-00 00:00:00';
/**
* Comment date (localized).
*
* @since 4.4.0
* @var string
*/
public $comment_date_gmt = '0000-00-00 00:00:00';
/**
* Comment content.
*
* @since 4.4.0
* @var string
*/
public $comment_content = '';
/**
* Comment karma.
*
* @since 4.4.0
* @var int
*/
public $comment_karma = 0;
/**
* Is this comment approved?
*
* @since 4.4.0
* @var string
*/
public $comment_approved = '1';
/**
* Comment agent.
*
* @since 4.4.0
* @var string
*/
public $comment_agent = '';
/**
* Comment type.
*
* @since 4.4.0
* @var string
*/
public $comment_type = 'comment';
/**
* Parent comment ID.
*
* @since 4.4.0
* @var int
*/
public $comment_parent = 0;
/**
* Comment user ID.
*
* @since 4.4.0
* @var int
*/
public $user_id = 0;
/**
* Stores the raw comment data array.
*
* @since 4.4.0
* @var array
*/
public $fields = array();
//... 其他方法
}
可以看到,这个类定义了一系列的属性,每个属性对应评论表(wp_comments
)中的一个字段。 比如$comment_author
对应评论者的名字,$comment_content
对应评论的内容等等。
用表格的形式总结一下:
属性名 | 类型 | 描述 | 对应数据库字段 |
---|---|---|---|
$comment_ID |
int |
评论 ID | comment_ID |
$comment_post_ID |
int |
评论所属文章 ID | comment_post_ID |
$comment_author |
string |
评论者姓名 | comment_author |
$comment_author_email |
string |
评论者邮箱 | comment_author_email |
$comment_author_url |
string |
评论者网站 | comment_author_url |
$comment_content |
string |
评论内容 | comment_content |
$comment_date |
string |
评论时间 | comment_date |
$comment_approved |
string |
评论是否审核通过 (0, 1, spam, trash) | comment_approved |
$comment_type |
string |
评论类型 (comment, trackback, pingback) | comment_type |
$user_id |
int |
评论者用户 ID(如果已登录) | user_id |
1.2 构造函数 __construct()
WP_Comment
类的构造函数是用来初始化对象属性的。通常,它会接收一个评论数据(可以是数组或对象),然后把这些数据赋值给相应的属性。
/**
* WP_Comment constructor.
*
* @since 4.4.0
*
* @param WP_Comment|object|array $comment Comment to populate comment data from.
*/
public function __construct( $comment = null ) {
if ( is_object( $comment ) ) {
foreach ( get_object_vars( $comment ) as $key => $value ) {
$this->$key = $value;
}
} elseif ( is_array( $comment ) ) {
foreach ( $comment as $key => $value ) {
$this->$key = $value;
}
}
if ( isset( $this->comment_ID ) ) {
$this->comment_ID = (int) $this->comment_ID;
}
$this->fields = (array) $comment;
}
这个构造函数会判断传入的$comment
参数的类型:
- 如果是对象: 遍历对象的所有属性,并赋值给
WP_Comment
对象的对应属性。 - 如果是数组: 遍历数组的所有键值对,并赋值给
WP_Comment
对象的对应属性。 - 都不是: 啥也不干,默默等待被赋值。
不管哪种情况,最后都会把原始的评论数据存储到$this->fields
属性中,方便以后使用。
1.3 获取评论数据的方法
WP_Comment
类还提供了一些方法来获取评论数据的不同形式。虽然大部分属性都是public的,可以直接访问,但使用方法可以进行一些格式化或者安全性处理。
例如:
get_comment_author()
: 获取评论作者名。get_comment_date( $format = '' )
: 获取评论日期,可以指定日期格式。get_comment_text()
: 获取评论内容。get_comment_link( $args = array() )
: 获取评论的链接。
这些方法通常会对数据进行一些处理,比如转义特殊字符,或者格式化日期。
例子:
假设我们已经有了一个WP_Comment
对象$comment
,我们可以这样获取评论的信息:
$author = $comment->get_comment_author(); // 直接访问属性
$date = $comment->get_comment_date('Y-m-d'); // 使用方法,格式化日期
$content = $comment->comment_content; // 直接访问属性
echo "评论作者:{$author}, 评论日期:{$date}, 评论内容:{$content}";
二、WP_Comment_Query
:评论的查询器
WP_Comment_Query
类是用来从数据库中查询评论的。它允许我们设置各种查询参数,比如根据文章 ID、作者、日期等等条件来筛选评论。
2.1 类的定义和属性
WP_Comment_Query
类也有很多属性,用来存储查询参数。
/**
* Core class used for querying comments.
*
* @since 3.1.0
*/
class WP_Comment_Query {
/**
* SQL query string.
*
* @since 3.1.0
* @access public
* @var string
*/
public $request;
/**
* List of comment IDs located by the query.
*
* @since 3.1.0
* @access public
* @var array
*/
public $comments;
/**
* The amount of comments found for the current query.
*
* @since 3.1.0
* @access public
* @var int
*/
public $comment_count = 0;
/**
* Query vars set by the user.
*
* @since 3.1.0
* @access public
* @var array
*/
public $query_vars = array();
/**
* The parsed query variables.
*
* @since 3.1.0
* @access public
* @var array
*/
public $query;
/**
* The default comment query variables.
*
* @since 3.1.0
* @access public
* @var array
*/
public $default_query = array(
'number' => '',
'offset' => '',
'orderby' => '',
'order' => 'DESC',
'fields' => 'all',
'meta_key' => '',
'meta_value' => '',
'meta_query' => '',
'date_query' => null, // See WP_Date_Query
'search' => '',
'comment__in' => '',
'comment__not_in' => '',
'comment_ID' => '',
'comment_author_email' => '',
'comment_author_url' => '',
'comment_author' => '',
'comment_author_IP' => '',
'comment_karma' => '',
'comment_approved' => '',
'comment_type' => '',
'comment_parent' => '',
'comment_post_ID' => '',
'comment_post_ID__in' => '',
'comment_post_ID__not_in' => '',
'user_id' => '',
'include_unapproved' => '',
);
//... 其他方法
}
其中,比较重要的属性包括:
$request
: 存储最终的 SQL 查询语句。$comments
: 存储查询结果,是一个WP_Comment
对象数组。$comment_count
: 存储查询到的评论总数。$query_vars
: 存储用户设置的查询参数。$query
: 存储解析后的查询参数。$default_query
: 存储默认的查询参数。
2.2 构造函数 __construct()
WP_Comment_Query
的构造函数接收一个参数,这个参数是一个数组,包含了各种查询参数。
/**
* WP_Comment_Query constructor.
*
* @since 3.1.0
*
* @param string|array $query Optional. Array or query string of comment query parameters.
*/
public function __construct( $query = '' ) {
$this->query_vars = wp_parse_args( $query );
$this->parse_query( $this->query_vars );
$this->query['fields'] = $this->get_fields();
// Only query for ids when 'count' is the only query var.
if ( array_keys( $this->query_vars ) === array( 'count' ) ) {
$this->query['fields'] = 'ids';
}
$this->get_comments();
}
这个构造函数主要做了以下几件事情:
- 使用
wp_parse_args()
函数,把传入的查询参数和默认参数合并。 - 调用
parse_query()
方法,解析查询参数。 - 调用
get_fields()
方法,获取需要返回的字段。 - 调用
get_comments()
方法,执行查询。
2.3 查询参数
WP_Comment_Query
支持非常多的查询参数,可以通过数组的形式传递给构造函数。下面列出一些常用的查询参数:
参数名 | 类型 | 描述 |
---|---|---|
number |
int |
返回评论的数量 |
offset |
int |
偏移量,从第几条评论开始返回 |
orderby |
string |
排序字段,比如comment_date 、comment_ID 等 |
order |
string |
排序方式,ASC 或DESC |
post_id (或comment_post_ID ) |
int |
只返回指定文章的评论 |
post_id__in (或comment_post_ID__in ) |
array |
只返回指定文章列表的评论 |
status (或comment_approved ) |
string |
返回指定状态的评论,比如approve 、hold 、spam 等 |
author_email (或comment_author_email ) |
string |
返回指定作者邮箱的评论 |
2.4 执行查询 get_comments()
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 WP_Comment objects, a list of comment IDs when 'fields' is 'ids',
* or the number of comments when 'count' is passed as a query var.
*/
public function get_comments() {
global $wpdb;
$comments = array();
/**
* Fires before the comment query is run.
*
* @since 3.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 array before the query is run.
*
* Passing a non-null value will short-circuit the query, returning
* the passed value instead.
*
* @since 3.7.0
*
* @param array|null $value An array of comments, or null to allow WP to run the query.
* @param WP_Comment_Query &$this The WP_Comment_Query instance (passed by reference).
*/
$comment_list = apply_filters_ref_array( 'comments_pre_query', array( null, &$this ) );
if ( ! is_null( $comment_list ) ) {
$this->comments = $comment_list;
return $this->comments;
}
$this->request = $this->get_sql();
if ( 'ids' === $this->query['fields'] ) {
$ids = $wpdb->get_col( $this->request );
return array_map( 'intval', $ids );
}
if ( 'count' === $this->query_vars['count'] ) {
$this->comment_count = (int) $wpdb->get_var( $this->request );
return $this->comment_count;
}
$comments = $wpdb->get_results( $this->request );
// Prime comment caches.
update_comment_cache( $comments );
// Convert to WP_Comment objects.
$this->comments = array_map( 'get_comment', $comments );
/**
* Fires after the comment query is run.
*
* @since 3.1.0
*
* @param array &$comments The array of comment results.
* @param WP_Comment_Query &$this The WP_Comment_Query instance (passed by reference).
*/
do_action_ref_array( 'comments_post_query', array( &$comments, &$this ) );
return $this->comments;
}
这个方法的主要步骤包括:
- 构建 SQL 查询语句 (
$this->get_sql()
)。 - 执行 SQL 查询 (
$wpdb->get_results()
)。 - 把查询结果转换成
WP_Comment
对象 (array_map( 'get_comment', $comments )
)。
2.5 获取 SQL 语句 get_sql()
get_sql()
方法负责根据查询参数构建 SQL 查询语句。这个方法比较复杂,因为它需要处理各种不同的查询参数,并把它们转换成 SQL 语句的 WHERE
子句。
例子:
假设我们要查询文章 ID 为 123 的所有已审核通过的评论,可以这样使用WP_Comment_Query
:
$args = array(
'post_id' => 123,
'status' => 'approve',
);
$comment_query = new WP_Comment_Query( $args );
$comments = $comment_query->get_comments();
if ( $comments ) {
foreach ( $comments as $comment ) {
echo "<p>{$comment->comment_author}: {$comment->comment_content}</p>";
}
} else {
echo "没有找到评论。";
}
三、WP_Comment
和 WP_Comment_Query
的交互
现在我们来聊聊WP_Comment
和WP_Comment_Query
是如何一起工作的。
WP_Comment_Query
发起查询: 我们创建一个WP_Comment_Query
对象,并传入查询参数。WP_Comment_Query
构建 SQL 语句:WP_Comment_Query
对象根据查询参数构建 SQL 查询语句。- 执行查询并获取数据:
WP_Comment_Query
对象执行 SQL 查询,从数据库中获取评论数据。 - 创建
WP_Comment
对象:WP_Comment_Query
对象把每一条评论数据都封装到一个WP_Comment
对象中。 - 返回
WP_Comment
对象数组:WP_Comment_Query
对象返回一个WP_Comment
对象数组,包含了所有查询到的评论。
简单来说,WP_Comment_Query
负责找到符合条件的评论数据,然后WP_Comment
负责把这些数据封装成对象,方便我们使用。
更详细的流程
-
调用
WP_Comment_Query
: 你的代码(比如主题文件或插件)创建一个WP_Comment_Query
实例,并传递一个包含查询参数的数组。$args = array( 'post_id' => get_the_ID(), // 获取当前文章 ID 'status' => 'approve', // 只获取已批准的评论 'number' => 10, // 最多获取 10 条评论 ); $comments_query = new WP_Comment_Query( $args ); $comments = $comments_query->get_comments();
-
WP_Comment_Query
构造 SQL:WP_Comment_Query
的构造函数解析查询参数,并将它们存储在内部属性中。然后,get_comments()
方法被调用。这个方法会调用get_sql()
方法来构建实际的 SQL 查询语句。get_sql()
方法会根据你提供的参数构建复杂的 SQL 查询,包括WHERE
子句、ORDER BY
子句和LIMIT
子句。 -
数据库查询:
get_comments()
方法使用$wpdb
对象(WordPress 的数据库抽象层)来执行 SQL 查询。$this->request = $this->get_sql(); // 构建 SQL 查询 $comments = $wpdb->get_results( $this->request ); // 执行查询
-
数据处理和
WP_Comment
对象创建: 数据库返回的结果通常是 PHP 对象或关联数组。get_comments()
方法遍历这些结果,并使用get_comment()
函数将每个结果转换成一个WP_Comment
对象。$this->comments = array_map( 'get_comment', $comments );
get_comment()
函数会检查缓存,如果评论已经存在于缓存中,则直接返回缓存的对象。否则,它会创建一个新的WP_Comment
对象,并将数据库结果中的数据填充到该对象中。 -
返回结果:
get_comments()
方法返回一个WP_Comment
对象数组。你的代码现在可以遍历这个数组,并使用WP_Comment
对象的方法来访问评论的各种属性。if ( $comments ) { foreach ( $comments as $comment ) { echo '<p>' . $comment->comment_author . ': ' . $comment->comment_content . '</p>'; } }
为什么要使用 WP_Comment
对象?
直接使用数据库查询结果也可以,但使用 WP_Comment
对象有几个优点:
- 封装性:
WP_Comment
对象将评论的所有相关数据封装在一起,方便访问和管理。 - 一致性: 无论评论来自哪个来源(数据库、缓存等),你都可以使用相同的方法来访问其属性。
- 扩展性:
WP_Comment
类可以被扩展,以添加自定义方法和属性。 - 缓存: WordPress 使用对象缓存来存储
WP_Comment
对象,以提高性能。
总结
WP_Comment
和WP_Comment_Query
是WordPress评论系统中两个非常重要的类。WP_Comment
负责封装评论数据,WP_Comment_Query
负责查询评论数据。它们一起工作,为我们提供了方便、高效的方式来管理评论。理解这两个类的原理,可以帮助我们更好地定制和扩展WordPress评论系统。
希望今天的讲解对你有所帮助!下次有机会再见!