我的博客评论是这样的:在后台开启了两层嵌套,并且利用 PHP 代码将原本不能直接按钮回复的第二层评论设置为可回复;为了使第二层回复的目标更加清晰,采用了@回复样式。

具体的改造过程和方法,可以参考WordPress 基于 Jquery 实现@回复的方法和照猫画虎的改进

使用过程中发现了如下问题:实际应用中对任一第二层评论的回复都是回复的第一层评论(有点绕,具体可以对比查看数据库中的 wp_comments 表中的 comment_parent),所以采用 willin 大师的 comment-mail-notify,也只能将评论通知发送到第一层评论同学的邮箱中,而你所@回复的同学,完全收不到任何提示(测试得出的结果)。为解决这个问题,昨晚临睡前就在笔记本上涂涂画画,把大概思路写了出来,今天把代码实现了,具体往下看!

对@回复的 JavaScript 代码的二次改造:

$('.comment-reply-link').click(function(){ //class=".depth-8" 子元素 class=".children" 下的 class=".reply" 的点击事件,注意:模板不同 HTML 结构可能不同,需调整!
	var rid= $(this).parent().parent().attr("id"); // 取得所回复的评论 id,可能需要调整!
	var rna= $(this).parent().parent().find('strong').text(); // 取得所回复的评论用户名,可能需要调整!
	var oric=$("#comment").attr("value").replace(/<a href="#(li-)?comment.*<\/a>(\n|\r\n)/g,'');
	$("#comment").attr("value","<a href=\"#"+rid+"\" class=\"at_reply\">@"+rna+"</a>\n" + oric).focus(); // 在输入框添加"@ 用户名" 和链接
});

改造的结果:

  1. 一次只能@回复一个人:每点击评论的回复按钮,都会将内容中的@回复 HTML 代码用正则去掉(如果存在),再重新添加当前回复的 ID。
  2. 无论如何点击回复,都不会造成已撰写的评论内容消失。

对被@回复提及的评论作者发送通知,代码插入到主题functions.php中:

function at_comment_mail_notify($comment_id) {
	$admin_email = get_option( 'admin_email' );
	$comment = get_comment($comment_id);// 获得评论
	$comment_post_ID = $comment->comment_post_ID;// 评论的文章的 ID
	$comment_content = trim($comment->comment_content);
	$comment_author_email = trim($comment->comment_author_email);
	if(preg_match('/\<a href=\"#(li-)?comment-/',$comment_content )){
		$at_id = preg_replace('/^\<a href="#(li-)?comment-(\d+).*/si','$2',$comment_content);
		if($at_id){
			global $wpdb;
			$at_comment = get_comment($at_id);// 被@ 的评论
			$at_comment_author_email = $at_comment->comment_author_email;
			$at_comment_post_ID = $at_comment->comment_post_ID;// 被@评论的文章 ID,判断被@的是否是同一篇文章
			$notify = $at_id ? $at_comment->comment_mail_notify : '0';	
			$spam_confirmed = $comment->comment_approved;
			$parent_id = $comment->comment_parent ? $comment->comment_parent : '';
			if($parent_id){
				$parent_email = get_comment($parent_id)->comment_author_email;
			}else{
				$parent_email = '';
			}
			if ($at_id != '' && $spam_confirmed != 'spam'  && $notify == '1' && $at_comment_post_ID == $comment_post_ID && $at_comment_author_email != $admin_email && $parent_email != $at_comment_author_email && $at_comment_author_email != $comment_author_email) {
				$wp_email = 'a@b.c'; // e-mail 發出點, no-reply 可改為可用的 e-mail.
				$to = trim(get_comment($at_id)->comment_author) . '<' . trim(get_comment($at_id)->comment_author_email) . '>';
				$subject = '您在 小虾的 Blog 的评论有了新回复';
				$message = '<div style="background:#E1E1E1;font-family:Arial,Helvetica,\'Hiragino Sans GB\',\'Microsoft YaHei\',SimSun;font-size:13px;padding:1em 0"><div style="background-color:#009BCA; color:#FFF;padding:1em 2em;margin:0 1em"><p><b>' . trim(get_comment($at_id)->comment_author) . '</b>,您好!</p></div><div style="background-color:snow;color:#333;padding:1em 2em;margin:0 1em;margin-top:2px"><p>您在《' . get_the_title($comment->comment_post_ID) . '》的评论为:<blockquote style="border:1px dashed #333;background:#FFF;padding:10px">'. trim(get_comment($at_id)->comment_content) . '</blockquote><p><b>' . trim($comment->comment_author) . '</b> @ 了您:</p><blockquote style="border:1px dashed #333;background:#FFF;padding:10px">'. trim($comment->comment_content) . '</blockquote><p>您可以 <a href="' . htmlspecialchars(get_comment_link($at_id)) . '">查看回复的完整内容</a> 。</p><br/><p>(此邮件由系统在 ' . gmdate('Y-m-d H:i:s', time()) . ' +0000 自动发出,请勿回复)</p></div><div style="text-align:right;padding:1em 2em"><a href="' . get_option('home') . '">' . html_entity_decode(get_option('blogname'), ENT_QUOTES) . '</a></div></div>';
				$from = "From: \" 小虾的 Blog\" <$wp_email>";
				$headers = "$from\nContent-Type: text/html; charset=\"UTF-8\"\n";
				wp_mail( $to, $subject, $message, $headers );
			}
		}
	}
}
add_action('comment_post', 'at_comment_mail_notify');// 函数名需要修改成不同的。

此函数可以对@回复对象发送评论通知,并且在 comment_mail_notify 的存在的情况下,也会对第一级评论作者发送通知。另外有几点说明:

  1. 此代码根据 willin 的 comment_mail_notify 改造而成。
  2. 此代码需要与 willin 的 comment_mail_notify 共存。
  3. PHP 中@回复的正则匹配必须与由 JavaScript 生成的@回复 HTML 代码相配合。
  4. 获取@回复对象 ID 的正则匹配可能存在不足,会根据使用效果逐渐完善。
  5. 也许会有未知 bug 导致发不出去通知,不过绝对不会影响博客的正常功能。

以上代码经过简单的测试,能够正确的对@回复对象发送评论通知。

  1. 同样遇到这个问题。我的也是两层套嵌。不过正则去除@好像不大管用。

    • @Ben
      JavaScript 生成的@回复 HTML 代码和主题有关系,JavaScript 和 PHP 中的正则表达式处理又得取决于前面生成的@代码,所以必须得将三者统一起来才行。
      我本地和主机上都测试过,收邮件和提取@回复对象的 comment-ID 都没有问题。
      如果可以的话你可以在换个邮箱再回复此留言,测试一下 :smile:

    • @小虾
      可能是我的主题加@没带回车,结果清不掉 :sad:
      :wink: 把回车去掉下用上了,很好用

    • @Ben
      下午的时候我又加了个$at_comment_author_email != $comment_author_email的判断,以避免自己@自己还发送通知。
      另外如果只收到一封关于此评论的通知邮件,就说明避免重复通知的代码工作还是正常的...