WordPress 评论者身份的秘密:wp_get_current_commenter()
源码剖析
各位观众,老司机开车了!今天咱们来扒一扒 WordPress 里一个看似不起眼,但实则关系到评论区用户体验的重要函数:wp_get_current_commenter()
。 顾名思义,这个函数的作用就是获取当前评论者的信息。但它到底是怎么知道“当前”是哪个评论者的呢? 答案藏在 Cookie 里!
准备好了吗?系好安全带,咱们直接上代码,边跑边聊!
一、wp_get_current_commenter()
函数概览
首先,我们来看一下 wp-includes/comment.php
文件中 wp_get_current_commenter()
函数的庐山真面目:
function wp_get_current_commenter() {
static $commenter = null;
if ( null !== $commenter ) {
return $commenter;
}
$commenter = array(
'comment_author' => '',
'comment_author_email' => '',
'comment_author_url' => '',
);
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
$commenter['comment_author'] = $user->display_name;
$commenter['comment_author_email'] = $user->user_email;
$commenter['comment_author_url'] = $user->user_url;
} else {
$commenter['comment_author'] = ( isset( $_COOKIE['comment_author_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_' . COOKIEHASH] ) : '';
$commenter['comment_author_email'] = ( isset( $_COOKIE['comment_author_email_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_email_' . COOKIEHASH] ) : '';
$commenter['comment_author_url'] = ( isset( $_COOKIE['comment_author_url_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_url_' . COOKIEHASH] ) : '';
}
$commenter = apply_filters( 'wp_get_current_commenter', $commenter );
return $commenter;
}
代码不长,但信息量很大。 咱们一行一行地分析:
-
静态变量缓存:
static $commenter = null; if ( null !== $commenter ) { return $commenter; }
这部分使用了静态变量
$commenter
。 它的作用是缓存结果,避免重复计算,提高性能。 第一次调用时$commenter
是null
, 后续调用直接返回缓存值。 这是个小技巧,但很实用。 -
初始化评论者信息:
$commenter = array( 'comment_author' => '', 'comment_author_email' => '', 'comment_author_url' => '', );
这里初始化了一个数组
$commenter
,用于存储评论者的姓名、邮箱和网址。 默认值都为空字符串。 -
判断用户是否登录:
if ( is_user_logged_in() ) { $user = wp_get_current_user(); $commenter['comment_author'] = $user->display_name; $commenter['comment_author_email'] = $user->user_email; $commenter['comment_author_url'] = $user->user_url; }
如果用户已经登录,
is_user_logged_in()
函数会返回true
。 此时,直接从当前登录用户的信息中获取姓名、邮箱和网址。 这样,对于登录用户,就不需要依赖 Cookie 了。 -
从 Cookie 中获取评论者信息 (重点来了!):
else { $commenter['comment_author'] = ( isset( $_COOKIE['comment_author_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_' . COOKIEHASH] ) : ''; $commenter['comment_author_email'] = ( isset( $_COOKIE['comment_author_email_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_email_' . COOKIEHASH] ) : ''; $commenter['comment_author_url'] = ( isset( $_COOKIE['comment_author_url_' . COOKIEHASH] ) ) ? stripslashes( $_COOKIE['comment_author_url_' . COOKIEHASH] ) : ''; }
如果用户未登录, 这部分代码就派上用场了。它尝试从 Cookie 中读取评论者的姓名、邮箱和网址。
$_COOKIE
超全局变量:$_COOKIE
是 PHP 提供的一个超全局变量,用于访问客户端发送的 Cookie。 它是一个关联数组,键是 Cookie 的名称,值是 Cookie 的值。isset()
函数:isset()
函数用于检查变量是否已设置并且非NULL
。 在这里,它用于判断对应的 Cookie 是否存在。- 三元运算符:
condition ? value_if_true : value_if_false
是一个简洁的条件判断语句。 如果condition
为真,则返回value_if_true
,否则返回value_if_false
。 stripslashes()
函数:stripslashes()
函数用于移除字符串中的反斜杠。 这是为了防止 SQL 注入等安全问题。 当数据写入 Cookie 时,可能会自动添加反斜杠来转义特殊字符。 读取 Cookie 时,需要移除这些反斜杠。COOKIEHASH
常量:COOKIEHASH
是 WordPress 定义的一个常量,用于增加 Cookie 名称的唯一性。 这样可以避免不同 WordPress 站点之间的 Cookie 冲突。 它的值通常是 WordPress 安装目录的 MD5 哈希值。
-
应用过滤器:
$commenter = apply_filters( 'wp_get_current_commenter', $commenter );
apply_filters()
函数是 WordPress 的钩子机制的一部分。它允许开发者通过添加过滤器来修改$commenter
数组。 这提供了很大的灵活性,可以自定义评论者信息的获取方式。 -
返回评论者信息:
return $commenter;
最终,函数返回包含了评论者姓名、邮箱和网址的数组。
二、Cookie 的生成:wp_set_comment_cookies()
既然 wp_get_current_commenter()
函数是从 Cookie 中读取评论者信息的, 那么 Cookie 是怎么生成的呢? 答案是: wp_set_comment_cookies()
函数。
这个函数通常在用户提交评论后被调用。 它会将评论者的姓名、邮箱和网址存储到 Cookie 中。 我们来看一下它的源码:
function wp_set_comment_cookies( $comment, $secure = false ) {
if ( ! is_object( $comment ) ) {
return;
}
$commenter = wp_get_current_commenter();
$comment_author_domain = '';
if ( defined( 'COOKIE_DOMAIN' ) && COOKIE_DOMAIN ) {
$comment_author_domain = COOKIE_DOMAIN;
}
$secure = apply_filters( 'wp_set_comment_cookies_secure', $secure, $comment );
setcookie( 'comment_author_' . COOKIEHASH, $comment->comment_author, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, $secure );
setcookie( 'comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, $secure );
setcookie( 'comment_author_url_' . COOKIEHASH, $comment->comment_author_url, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, $secure );
if ( is_ssl() ) {
setcookie( 'comment_author_' . COOKIEHASH, $comment->comment_author, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, true );
setcookie( 'comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, true );
setcookie( 'comment_author_url_' . COOKIEHASH, $comment->comment_author_url, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, true );
}
}
我们来解读一下:
-
参数校验:
if ( ! is_object( $comment ) ) { return; }
函数首先检查传入的
$comment
参数是否是一个对象。 如果不是,则直接返回,不执行任何操作。 -
获取当前评论者信息:
$commenter = wp_get_current_commenter();
这里调用了我们刚刚分析的
wp_get_current_commenter()
函数,获取当前的评论者信息。 虽然这里获取了信息,但后面并没有直接使用,而是直接从$comment
对象中获取数据。 -
设置 Cookie 的域名:
$comment_author_domain = ''; if ( defined( 'COOKIE_DOMAIN' ) && COOKIE_DOMAIN ) { $comment_author_domain = COOKIE_DOMAIN; }
这部分代码用于设置 Cookie 的域名。 如果定义了
COOKIE_DOMAIN
常量,则使用该常量的值作为 Cookie 的域名。 否则,使用当前站点的域名。 这决定了 Cookie 的作用范围。 -
setcookie()
函数:setcookie( 'comment_author_' . COOKIEHASH, $comment->comment_author, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, $secure ); setcookie( 'comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, $secure ); setcookie( 'comment_author_url_' . COOKIEHASH, $comment->comment_author_url, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, $secure );
这部分代码是核心。 它使用 PHP 的
setcookie()
函数来设置 Cookie。- 参数说明:
name
: Cookie 的名称。 这里使用了comment_author_
、comment_author_email_
和comment_author_url_
作为前缀, 并加上了COOKIEHASH
常量,以保证唯一性。value
: Cookie 的值。 这里分别使用了$comment->comment_author
、$comment->comment_author_email
和$comment->comment_author_url
。expires
: Cookie 的过期时间。 这里使用了time() + YEAR_IN_SECONDS
,表示 Cookie 将在一年后过期。path
: Cookie 的路径。 这里使用了COOKIEPATH
常量,通常是 WordPress 的根目录。domain
: Cookie 的域名。 这里使用了之前设置的$comment_author_domain
变量。secure
: 指示 Cookie 是否仅通过安全 HTTPS 连接传输。 设置为 true 时,Cookie 只能通过 HTTPS 连接发送。
- 参数说明:
-
HTTPS 安全性:
if ( is_ssl() ) { setcookie( 'comment_author_' . COOKIEHASH, $comment->comment_author, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, true ); setcookie( 'comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, true ); setcookie( 'comment_author_url_' . COOKIEHASH, $comment->comment_author_url, time() + YEAR_IN_SECONDS, COOKIEPATH, $comment_author_domain, true ); }
如果当前站点使用了 HTTPS, 这部分代码会再次设置 Cookie,并将
secure
参数设置为true
。 这样可以确保 Cookie 只能通过 HTTPS 连接传输,提高安全性。
三、Cookie 相关配置:wp-config.php
Cookie 的行为受到 wp-config.php
文件中一些常量的影响。 了解这些常量可以更好地理解 Cookie 的工作方式。
常量名称 | 作用 | 默认值 |
---|---|---|
COOKIEHASH |
用于增加 Cookie 名称的唯一性,防止不同 WordPress 站点之间的 Cookie 冲突。 | WordPress 安装目录的 MD5 哈希值 |
COOKIE_DOMAIN |
设置 Cookie 的域名。 如果未设置,则使用当前站点的域名。 设置为 false 或空字符串可以防止 Cookie 被发送到其他域。 |
空字符串 (使用当前站点域名) |
COOKIEPATH |
设置 Cookie 的路径。 通常是 WordPress 的根目录。 | / (WordPress 根目录) |
SITECOOKIEPATH |
设置站点 Cookie 的路径。 用于区分后台 Cookie 和前台 Cookie。 | / (WordPress 根目录) |
ADMIN_COOKIE_PATH |
设置后台 Cookie 的路径。 用于区分后台 Cookie 和前台 Cookie。 | SITECOOKIEPATH . 'wp-admin' |
SECURE_AUTH_COOKIE |
身份验证 Cookie 的名称。 | wordpress_sec_${COOKIEHASH} |
AUTH_COOKIE |
常规身份验证 Cookie 的名称。 | wordpress_${COOKIEHASH} |
LOGGED_IN_COOKIE |
登录 Cookie 的名称。 | wordpress_logged_in_${COOKIEHASH} |
TEST_COOKIE |
用于测试 Cookie 是否已启用的 Cookie 的名称。 | wp-test-cookie |
四、总结
通过上面的分析,我们了解了 wp_get_current_commenter()
函数是如何从 Cookie 中获取评论者信息的。 简单总结一下:
-
wp_get_current_commenter()
函数首先检查用户是否登录。 如果已登录,则直接从用户信息中获取姓名、邮箱和网址。 -
如果用户未登录,则尝试从 Cookie 中读取评论者信息。 Cookie 的名称包含
COOKIEHASH
常量,以保证唯一性。 -
wp_set_comment_cookies()
函数在用户提交评论后被调用,用于设置 Cookie。 -
Cookie 的行为受到
wp-config.php
文件中一些常量的影响,例如COOKIE_DOMAIN
和COOKIEPATH
。
五、一些思考
-
安全性: 虽然 Cookie 可以方便地存储评论者信息,但也存在安全风险。 例如,Cookie 可能会被篡改或窃取。 因此,在处理 Cookie 时,需要注意安全性,例如使用 HTTPS 连接、对 Cookie 进行加密等。
-
隐私: Cookie 涉及到用户隐私。 应该明确告知用户网站使用了 Cookie,并提供管理 Cookie 的选项。 符合 GDPR 等隐私法规的要求。
-
替代方案: 除了 Cookie,还可以使用其他方式来存储评论者信息,例如 Local Storage 或 Session Storage。 这些方案各有优缺点,需要根据实际情况选择。
-
缓存: 就像函数开头展示的那样, 静态变量缓存是很常用的优化手段,可以避免重复计算,提高性能。
好了,今天的讲座就到这里。 希望大家有所收获! 下次再见!