阐述 WordPress `wp_get_current_commenter()` 函数的源码:如何从 `Cookie` 中获取评论者信息。

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;
}

代码不长,但信息量很大。 咱们一行一行地分析:

  1. 静态变量缓存:

    static $commenter = null;
    
    if ( null !== $commenter ) {
        return $commenter;
    }

    这部分使用了静态变量 $commenter。 它的作用是缓存结果,避免重复计算,提高性能。 第一次调用时 $commenternull, 后续调用直接返回缓存值。 这是个小技巧,但很实用。

  2. 初始化评论者信息:

    $commenter = array(
        'comment_author'       => '',
        'comment_author_email' => '',
        'comment_author_url'   => '',
    );

    这里初始化了一个数组 $commenter,用于存储评论者的姓名、邮箱和网址。 默认值都为空字符串。

  3. 判断用户是否登录:

    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 了。

  4. 从 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 哈希值。
  5. 应用过滤器:

    $commenter = apply_filters( 'wp_get_current_commenter', $commenter );

    apply_filters() 函数是 WordPress 的钩子机制的一部分。它允许开发者通过添加过滤器来修改 $commenter 数组。 这提供了很大的灵活性,可以自定义评论者信息的获取方式。

  6. 返回评论者信息:

    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 );
    }
}

我们来解读一下:

  1. 参数校验:

    if ( ! is_object( $comment ) ) {
        return;
    }

    函数首先检查传入的 $comment 参数是否是一个对象。 如果不是,则直接返回,不执行任何操作。

  2. 获取当前评论者信息:

    $commenter = wp_get_current_commenter();

    这里调用了我们刚刚分析的 wp_get_current_commenter() 函数,获取当前的评论者信息。 虽然这里获取了信息,但后面并没有直接使用,而是直接从 $comment 对象中获取数据。

  3. 设置 Cookie 的域名:

    $comment_author_domain = '';
    
    if ( defined( 'COOKIE_DOMAIN' ) && COOKIE_DOMAIN ) {
        $comment_author_domain = COOKIE_DOMAIN;
    }

    这部分代码用于设置 Cookie 的域名。 如果定义了 COOKIE_DOMAIN 常量,则使用该常量的值作为 Cookie 的域名。 否则,使用当前站点的域名。 这决定了 Cookie 的作用范围。

  4. 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 连接发送。
  5. 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 中获取评论者信息的。 简单总结一下:

  1. wp_get_current_commenter() 函数首先检查用户是否登录。 如果已登录,则直接从用户信息中获取姓名、邮箱和网址。

  2. 如果用户未登录,则尝试从 Cookie 中读取评论者信息。 Cookie 的名称包含 COOKIEHASH 常量,以保证唯一性。

  3. wp_set_comment_cookies() 函数在用户提交评论后被调用,用于设置 Cookie。

  4. Cookie 的行为受到 wp-config.php 文件中一些常量的影响,例如 COOKIE_DOMAINCOOKIEPATH

五、一些思考

  • 安全性: 虽然 Cookie 可以方便地存储评论者信息,但也存在安全风险。 例如,Cookie 可能会被篡改或窃取。 因此,在处理 Cookie 时,需要注意安全性,例如使用 HTTPS 连接、对 Cookie 进行加密等。

  • 隐私: Cookie 涉及到用户隐私。 应该明确告知用户网站使用了 Cookie,并提供管理 Cookie 的选项。 符合 GDPR 等隐私法规的要求。

  • 替代方案: 除了 Cookie,还可以使用其他方式来存储评论者信息,例如 Local Storage 或 Session Storage。 这些方案各有优缺点,需要根据实际情况选择。

  • 缓存: 就像函数开头展示的那样, 静态变量缓存是很常用的优化手段,可以避免重复计算,提高性能。

好了,今天的讲座就到这里。 希望大家有所收获! 下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注