WordPress 评论者身份之谜:wp_get_current_commenter()
函数源码深度剖析
各位观众,欢迎来到今天的“WordPress 源码解密”讲座!今天我们要聊的是一个非常重要,但又常常被忽视的函数:wp_get_current_commenter()
。 它负责从用户的 Cookie
中提取评论者的信息,对于评论功能来说,绝对是幕后英雄般的存在。 那么,让我们一起扒开它的源代码,看看它到底是如何工作的,顺便也学习一些 Cookie
操作的小技巧。
1. 开场白:Cookie
的前世今生
在深入源码之前,先简单回顾一下 Cookie
的概念。 Cookie
就像网站发给浏览器的小纸条,上面记录着一些信息,比如用户的登录状态、偏好设置等等。 当用户再次访问网站时,浏览器会把这些小纸条(Cookie
)带上,网站就能“认出”用户了。 是不是有点像暗号接头?
评论功能也需要 Cookie
来记住用户的身份。 如果用户之前发表过评论,我们就可以通过 Cookie
自动填充他们的姓名、邮箱等信息,省去重复输入的麻烦。 而 wp_get_current_commenter()
函数,正是负责从 Cookie
中读取这些信息的关键角色。
2. 源码探秘: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;
}
$comment_cookie_domain = '';
if ( defined( 'COOKIE_DOMAIN' ) && COOKIE_DOMAIN ) {
$comment_cookie_domain = COOKIE_DOMAIN;
}
$commenter = wp_parse_args(
wp_unslash( $_COOKIE ),
array(
'comment_author_' . sanitize_title( get_option( 'blogname' ) ) => '',
'comment_author_email_' . sanitize_title( get_option( 'blogname' ) ) => '',
'comment_author_url_' . sanitize_title( get_option( 'blogname' ) ) => '',
)
);
$commenter = (object) array(
'comment_author' => isset( $commenter[ 'comment_author_' . sanitize_title( get_option( 'blogname' ) ) ] ) ? trim( $commenter[ 'comment_author_' . sanitize_title( get_option( 'blogname' ) ) ] ) : '',
'comment_author_email' => isset( $commenter[ 'comment_author_email_' . sanitize_title( get_option( 'blogname' ) ) ] ) ? trim( $commenter[ 'comment_author_email_' . sanitize_title( get_option( 'blogname' ) ) ] ) : '',
'comment_author_url' => isset( $commenter[ 'comment_author_url_' . sanitize_title( get_option( 'blogname' ) ) ] ) ? trim( $commenter[ 'comment_author_url_' . sanitize_title( get_option( 'blogname' ) ) ] ) : '',
'comment_author_domain' => $comment_cookie_domain,
);
return $commenter;
}
别被这一堆代码吓到,我们一步一步来分析。
2.1. 静态变量缓存:提高效率的小技巧
static $commenter = null;
if ( null !== $commenter ) {
return $commenter;
}
这段代码使用了静态变量 $commenter
。 静态变量的特点是,函数每次被调用时,它只会被初始化一次。 也就是说,如果 $commenter
已经被赋值过了,函数就会直接返回它的值,而不会重复执行后面的代码。 这样做的好处是,可以提高函数的执行效率,避免重复读取 Cookie
。 毕竟,Cookie
的读取也是需要消耗资源的。
2.2. 获取 Cookie
域名:决定 Cookie
的作用范围
$comment_cookie_domain = '';
if ( defined( 'COOKIE_DOMAIN' ) && COOKIE_DOMAIN ) {
$comment_cookie_domain = COOKIE_DOMAIN;
}
这段代码尝试获取 COOKIE_DOMAIN
常量的值。 这个常量定义了 Cookie
的作用域,也就是 Cookie
对哪些域名有效。 如果 COOKIE_DOMAIN
没有定义,或者为空字符串,那么 Cookie
的作用域就是当前域名。 这个参数在设置 Cookie
的时候非常重要,错误的域名可能导致 Cookie
无法被正确读取。
2.3. 读取 Cookie
数据:核心逻辑
$commenter = wp_parse_args(
wp_unslash( $_COOKIE ),
array(
'comment_author_' . sanitize_title( get_option( 'blogname' ) ) => '',
'comment_author_email_' . sanitize_title( get_option( 'blogname' ) ) => '',
'comment_author_url_' . sanitize_title( get_option( 'blogname' ) ) => '',
)
);
这部分代码是整个函数的关键。 它主要做了两件事:
-
wp_unslash( $_COOKIE )
: 首先,它使用wp_unslash()
函数对$_COOKIE
超全局数组进行处理。wp_unslash()
函数的作用是移除由magic_quotes_gpc
自动添加的反斜杠。 虽然magic_quotes_gpc
在 PHP 5.4 中已经被移除,但 WordPress 为了兼容性,仍然保留了这个函数。 目的是确保从Cookie
中读取的数据是原始的,没有被转义。 -
wp_parse_args()
: 然后,它使用wp_parse_args()
函数将$_COOKIE
数组与一个默认的参数数组进行合并。wp_parse_args()
函数的作用类似于array_merge()
,但是它有一些额外的特性,比如可以处理对象。 在这里,它将$_COOKIE
数组作为用户提供的参数,将一个包含默认值的数组作为默认参数。默认参数数组定义了三个
Cookie
的名称:comment_author_{blogname}
comment_author_email_{blogname}
comment_author_url_{blogname}
其中,
{blogname}
会被替换为博客名称的sanitize_title()
结果。sanitize_title()
函数会将博客名称转换为一个 URL 友好的字符串,比如将 "My Awesome Blog" 转换为 "my-awesome-blog"。 这样做的好处是可以避免Cookie
名称冲突,特别是当你的网站使用了多个 WordPress 站点时。wp_parse_args()
函数会将$_COOKIE
数组中与默认参数数组中键名相同的元素的值,赋值给$commenter
数组。 如果$_COOKIE
数组中没有相应的键名,那么$commenter
数组中对应的元素的值就会使用默认值(空字符串)。
2.4. 创建对象并赋值:整理数据
$commenter = (object) array(
'comment_author' => isset( $commenter[ 'comment_author_' . sanitize_title( get_option( 'blogname' ) ) ] ) ? trim( $commenter[ 'comment_author_' . sanitize_title( get_option( 'blogname' ) ) ] ) : '',
'comment_author_email' => isset( $commenter[ 'comment_author_email_' . sanitize_title( get_option( 'blogname' ) ) ] ) ? trim( $commenter[ 'comment_author_email_' . sanitize_title( get_option( 'blogname' ) ) ] ) : '',
'comment_author_url' => isset( $commenter[ 'comment_author_url_' . sanitize_title( get_option( 'blogname' ) ) ] ) ? trim( $commenter[ 'comment_author_url_' . sanitize_title( get_option( 'blogname' ) ) ] ) : '',
'comment_author_domain' => $comment_cookie_domain,
);
这段代码将 $commenter
数组转换为一个对象,并对其中的值进行处理。 具体来说,它做了以下几件事:
-
数组转对象: 使用
(object) array()
将数组转换为对象。 这样做的好处是可以更方便地访问对象属性,比如可以使用$commenter->comment_author
来获取评论者的姓名。 -
isset()
判断: 使用isset()
函数判断$commenter
数组中是否存在相应的键名。 这样做可以避免访问不存在的键名时出现错误。 -
trim()
函数: 使用trim()
函数去除字符串两端的空格。 这样做可以确保评论者的姓名、邮箱等信息没有多余的空格。 -
赋值: 将处理后的值赋值给对象的相应属性。
-
设置
comment_author_domain
: 将之前获取的Cookie
域名赋值给comment_author_domain
属性。
2.5. 返回结果:大功告成
return $commenter;
最后,函数返回 $commenter
对象,其中包含了从 Cookie
中读取的评论者信息。
3. 案例分析:模拟 Cookie
设置与读取
为了更好地理解 wp_get_current_commenter()
函数的工作原理,我们可以模拟一下 Cookie
的设置与读取过程。
3.1. 设置 Cookie
假设我们要在用户发表评论后,设置 Cookie
来保存他们的姓名、邮箱和网址。 可以使用 setcookie()
函数来实现:
$comment_author = '张三';
$comment_author_email = '[email protected]';
$comment_author_url = 'https://example.com';
$blogname = get_option( 'blogname' );
$cookie_name_author = 'comment_author_' . sanitize_title( $blogname );
$cookie_name_email = 'comment_author_email_' . sanitize_title( $blogname );
$cookie_name_url = 'comment_author_url_' . sanitize_title( $blogname );
$cookie_domain = defined( 'COOKIE_DOMAIN' ) && COOKIE_DOMAIN ? COOKIE_DOMAIN : '';
setcookie( $cookie_name_author, $comment_author, time() + 3600 * 24 * 30, COOKIEPATH, $cookie_domain );
setcookie( $cookie_name_email, $comment_author_email, time() + 3600 * 24 * 30, COOKIEPATH, $cookie_domain );
setcookie( $cookie_name_url, $comment_author_url, time() + 3600 * 24 * 30, COOKIEPATH, $cookie_domain );
这段代码首先定义了评论者的姓名、邮箱和网址。 然后,它使用 get_option( 'blogname' )
函数获取博客名称,并使用 sanitize_title()
函数将其转换为 URL 友好的字符串。 接着,它根据博客名称生成 Cookie
的名称。 最后,它使用 setcookie()
函数设置 Cookie
。
setcookie()
函数的参数如下:
name
:Cookie
的名称。value
:Cookie
的值。expire
:Cookie
的过期时间,Unix 时间戳。 这里设置为 30 天后过期。path
:Cookie
的有效路径。COOKIEPATH
常量定义了 WordPress 的Cookie
路径,通常是网站的根目录。domain
:Cookie
的有效域名。COOKIE_DOMAIN
常量定义了 WordPress 的Cookie
域名。
3.2. 读取 Cookie
现在,我们可以使用 wp_get_current_commenter()
函数来读取 Cookie
中的信息:
$commenter = wp_get_current_commenter();
echo '姓名:' . $commenter->comment_author . '<br>';
echo '邮箱:' . $commenter->comment_author_email . '<br>';
echo '网址:' . $commenter->comment_author_url . '<br>';
这段代码首先调用 wp_get_current_commenter()
函数获取 $commenter
对象。 然后,它使用 echo
语句将 $commenter
对象的属性值输出到页面上。
如果 Cookie
设置成功,并且 wp_get_current_commenter()
函数能够正确读取 Cookie
中的信息,那么页面上将会显示评论者的姓名、邮箱和网址。
4. 常见问题与注意事项
在使用 wp_get_current_commenter()
函数时,需要注意以下几点:
-
Cookie
禁用: 如果用户禁用了Cookie
,那么wp_get_current_commenter()
函数将无法读取任何信息。 因此,在评论表单中,需要提供一个选项,让用户手动输入他们的姓名、邮箱和网址。 -
Cookie
过期:Cookie
有过期时间。 如果Cookie
已经过期,那么wp_get_current_commenter()
函数将无法读取任何信息。 因此,需要定期更新Cookie
的过期时间。 -
Cookie
安全:Cookie
可能会被恶意用户篡改。 因此,需要对Cookie
进行加密处理,以防止Cookie
中的信息被泄露。 -
多站点环境: 在多站点环境中,需要确保每个站点的
Cookie
名称是唯一的,以避免Cookie
冲突。 可以使用sanitize_title( get_option( 'blogname' ) )
函数来生成唯一的Cookie
名称。 -
COOKIE_DOMAIN
常量: 正确配置COOKIE_DOMAIN
常量至关重要。 错误的配置可能导致Cookie
在不同的子域名之间无法共享,或者根本无法被读取。 -
缓存问题: 由于
wp_get_current_commenter()
使用了静态变量进行缓存,如果Cookie
被修改,缓存可能不会立即更新。 可以考虑在某些情况下手动清除缓存。
5. 总结
wp_get_current_commenter()
函数虽然看起来简单,但它在 WordPress 的评论功能中扮演着重要的角色。 它负责从 Cookie
中读取评论者的信息,为用户提供更好的评论体验。 通过深入分析它的源码,我们可以更好地理解 Cookie
的工作原理,以及 WordPress 如何处理 Cookie
数据。 希望今天的讲座能帮助大家更好地掌握 WordPress 开发技巧!
功能 | 描述 |
---|---|
读取 Cookie | 从 $_COOKIE 超全局数组中读取评论者的姓名、邮箱和网址等信息。 |
缓存数据 | 使用静态变量缓存读取到的评论者信息,避免重复读取 Cookie ,提高效率。 |
处理数据 | 使用 wp_unslash() 函数移除反斜杠,使用 trim() 函数去除字符串两端的空格,确保数据的准确性。 |
安全性 | 通过 sanitize_title() 函数对博客名称进行处理,生成唯一的 Cookie 名称,避免 Cookie 冲突。 |
对象化 | 将读取到的评论者信息转换为对象,方便访问对象属性。 |
配置域名 | 获取 COOKIE_DOMAIN 常量的值,用于设置 Cookie 的作用域。 |
今天的分享就到这里,谢谢大家!希望大家能从这次源码剖析中学到一些实用的技巧,并在实际开发中灵活运用。 记住,理解代码背后的逻辑,才能更好地驾驭它! 下次再见!