WordPress Ajax 提交评论的实现

评论(61)

一直对 WordPress 的 Ajax 交互研究感兴趣,也一直很关注于这方面的技术,谈到 WordPress Ajax 就不得不谈到评论 Ajax提交,作为一个博客、论坛评论的 Ajax 提交不仅可以改善用户体验,还可以大幅缩减服务器开支,毕竟输出单条评论内容比重新组织输出一个页面要简单的多。 虽说现在访问量一直比较低,不存在服务器压力的问题,但一向注重用户体验的我,当然不能放弃这么一个提升用户体验的机会。今天抽了一下午的空,把这个主题的 Ajax 评论提交初步完成了。

直接开门见山,直接上代码:(原理及思路在最后)
根据自己主题不同结构,以下代码请自行调整。

WordPress Ajax 提交评论 PHP 代码

在主题 function.php 文件中加入如下部分。

//以下大部分代码出自 yinheli 经由该部分代码,排除部分错误、优化精简得出以下代码。
//yinheli博客不做了,所以这里就不给链接了。
//Edited by XiangZi DEC.17TH 2011
function fail($s) {//虚拟错误头部分
    header('HTTP/1.0 500 Internal Server Error');
    echo $s;
    exit;
}
function ajax_post_comment_slow (){
	fail('用不用说这么快?想好了再说!');
}
//评论太快输出代码。
add_filter('comment_flood_trigger','ajax_post_comment_slow', 0);
//挂一个评论太快,返回内容的钩子
function ajax_comment(){
// Ajax php 响应部分代码
if($_POST['action'] == 'ajax_comment') {
    global $wpdb, $db_check;
        // Check DB
        if(!$wpdb->dbh) {
            echo('Our database has issues. Try again later.');
			die();
        } 
nocache_headers();
$comment_post_ID = (int) $_POST['comment_post_ID'];
 $status = $wpdb->get_row("SELECT post_status, comment_status FROM $wpdb->posts WHERE ID = '$comment_post_ID'");
if ( empty($status->comment_status) ) {
//这一套判断貌似抄的 wp 源代码 。详见:include/comment.php
    do_action('comment_id_not_found', $comment_post_ID);
    fail('The post you are trying to comment on does not currently exist in the database.');
} elseif ( 'closed' ==  $status->comment_status ) {
    do_action('comment_closed', $comment_post_ID);;
    fail('Sorry, comments are closed for this item.');
} elseif ( in_array($status->post_status, array('draft', 'pending') ) ) {
    do_action('comment_on_draft', $comment_post_ID);
    fail('The post you are trying to comment on has not been published.');
}
$comment_author       = trim(strip_tags($_POST['author']));
$comment_author_email = trim($_POST['email']);
$comment_author_url   = trim($_POST['url']);
$comment_content      = trim($_POST['comment']);
// If the user is logged in
$user = wp_get_current_user();
if ( $user->ID ) {
    $comment_author       = $wpdb->escape($user->display_name);
    $comment_author_email = $wpdb->escape($user->user_email);
    $comment_author_url   = $wpdb->escape($user->user_url);
    if ( current_user_can('unfiltered_html') ) {
        if ( wp_create_nonce('unfiltered-html-comment_' . $comment_post_ID) != $_POST['_wp_unfiltered_html_comment'] ) {
            kses_remove_filters(); // start with a clean slate
            kses_init_filters(); // set up the filters
        }
    }
} else {
    if ( get_option('comment_registration') )
        fail('火星人?注册个?');
}
$comment_type = '';
if ( get_option('require_name_email') && !$user->ID ) {
    if ( 6> strlen($comment_author_email) || '' == $comment_author )
        fail('Oopps,名字[Name]或邮箱[email]不对。');
    elseif ( !is_email($comment_author_email))
        fail('Oopps,邮箱地址[Email]不对。');
}
if ( '' == $comment_content )
    fail('是不是应该写点什么再提交?');
// Simple duplicate check
$dupe = "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = '$comment_post_ID' AND ( comment_author = '$comment_author' ";
if ( $comment_author_email ) $dupe .= "OR comment_author_email = '$comment_author_email' ";
$dupe .= ") AND comment_content = '$comment_content' LIMIT 1";
if ( $wpdb->get_var($dupe) ) {
    fail('评论重复了!有木有!');
}
$commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'user_ID');
if( !$user->ID ){
	$result_set = $wpdb->get_results("SELECT display_name, user_email FROM $wpdb->users WHERE display_name = '" . $comment_author . "' OR user_email = '" . $comment_author_email . "'");
	if ($result_set) {
	if ($result_set[0]->display_name == $comment_author){
	fail('博主你也敢冒充?');
	} else {
	fail('博主你也敢冒充?');
	}
	}
}
$comment_id = wp_new_comment( $commentdata );
$comment = get_comment($comment_id);
 
if( !$user->ID ){
	setcookie('comment_author_' . COOKIEHASH, $comment->comment_author, time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
	setcookie('comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
	setcookie('comment_author_url_' . COOKIEHASH, clean_url($comment->comment_author_url), time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
}
@header('Content-type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset'));
	xz_comment($comment, null);//这是我的调用评论函数,换成你的函数名。
	die();
}
}
add_action('init', 'ajax_comment');

Javascript 中代码

注意:以下代码需要 Jquery 框架支援。
javascript onload 代码中加入以下部分。

if (jQuery('#commentform').length) {
    jQuery('#commentform').submit(function(){    
// 截获提交动作
//ID为 commentform 的表单提交时发生的函数,也就是整个留言输入框 form 的ID。
		var ajaxCommentsURL = window.location.href;
        jQuery.ajax({
            url: ajaxCommentsURL,
            data: jQuery('#commentform').serialize()+'&action=ajax_comment',    
            type: 'POST',
            beforeSend: function() {
                jQuery('#commenterror').hide();
                jQuery('#commentload').fadeIn();
            },
            error: function(request) {    //发生错误时
                jQuery('#commenterror').html(request.responseText);
                jQuery('#commentload').hide();    //隐藏  submit
                jQuery('#commenterror').fadeIn(); //显示 error 
            },
            success: function(data) {
                jQuery('textarea').each(function(){
                    this.value='';
                });
                jQuery('#commenterror').fadeOut();
                if(jQuery(".commentlist li.comment").first().length != 0){jQuery(".commentlist li.comment").first().before(data)}   
                else {jQuery("ol.commentlist").append(data)}
                jQuery(".commentlist li.comment").first().hide(0,function(){$(this).slideDown(1000)});
                jQuery('#cmt-submit').attr('disabled', true).css({"background-color":"#6C6C6C","color":"#E0E0E0"});
                jQuery('#commentload').fadeOut(1600);
		setTimeout(function() {
                jQuery('#cmt-submit').removeAttr('disabled').css({"background-color":"#0086C5","color":"#FFFFFF"});
                },3000); 
            }
        });
       return false;
   } );
}

注:代码仍有改进需求,因为没有时间,所以就没有再进化。

CSS 代码

css 随意部分添加。

#commentload,#commenterror{
	display: none;
	margin: 5px 0 0 0;
	color:#D29A04;
	float: left;
	font-size:16px;
	padding:0 0 0 20px;
}
#commentload{
	background: url("img/loading.gif") no-repeat bottom left ;
}
#commenterror{
	background: url("img/error.png") no-repeat bottom left ;
}

原理、思路

原理:

  1. Javascript 提交数据
  2. php响应并输出结果
  3. Javascript 得到结果并显示

思路:

  1. 点击提交按钮后,Javascript 截获提交动作
  2. 截获提交的各项数据(Name、Email、Web、Comment-text)
  3. 利用 Javascript Jquery 模拟浏览器提交POST(Name、Email、Web、Comment-text)请求之WordPress
  4. Function.php 文件中构造一个接受请求的函数,即本列中ajax_comment函数
  5. 如果请求无错误,输出正确结果
  6. 如果请求有错误,输出错误结果
  7. Javascript 获得正确结果,动态添加到评论列表中
  8. Javascript 获得错误结果,动态添加到提交提示栏

改进

样式方面,我确实没什么美感,所以正在学习中。
提交按钮在点击至获得返回结果后3秒的时间里应该都是变灰失效状态,这一点之前因为在本机测试,提交瞬间完成没有注意到,远程测试的时候发现了,但要改的话还要进行测试,时间太紧就不改了,有机会再改进一下。

总结

因为 WordPress 主题中评论样式的自由性、多样性,所以貌似至今一直没有一款通用性的AJAX 评论插件,
一些高手也只能在优化自己博客之余,把思路和部分通用核心代码做一下公布,
所以想要实现一些炫酷的功能要不有高人帮你,
要不你就只能好好学代码,期待有一日能够厚积薄发了。
效果请自行提交评论验证。





转载请注明转自: WordPress Ajax 提交评论的实现

  1. 学习

  2. 看看效果,学习学习

  3. 我是来看ajax效果的~囧~

  4. 不错

  5. @vickai
    这个解决方案能够和我之前的主题无缝链接,至于和其他主题需要些许的调整。
    wordpress 的折腾主要是从实例中学原理,在实践中张技能,
    祝你成功。

  6. 拜读了一下上面的代码,有几个地方还需要测试调整一下,检测评论是否关闭那个地方多了一个分号(虽然多了一个也能正常运行)。还有文章的状态检测那个地方,文章还有加密和私有两种状态。

  7. 我想测试一下评论,谢谢

  8. 不错不错,就用这个了

  9. @loo
    add_action('init', 'ajax_comment');
    就这句将名称为ajax_comment的动作挂载到wp中
    参考jquery发起的ajax请求
    data: jQuery('#commentform').serialize()+'&action=ajax_comment',

  10. 上面的实现的评论功能,怎样和functions.php 中的ajax_comment() 方法交互,在教材上看到的都是使用某个文件而不是某个文件中的方法。

  11. 楼主介绍的很详细啊,正打算给我的blog加上ajax评论功能!

  12. 另外一种方法。

  13. 嘛,不错!!

  14. @稻草人
    感觉起来确实比较复杂,
    但有一定js基础的人看要简单好多,
    主要是ajax的应用。

  15. 这套思路其实不是很好理解

  16. 感觉好复杂。。。

  17. @章郎虫
    是啊,这套思路其实不是很好理解,
    关键是牵扯的语言太多,
    看到你的博客用的AJAX评论插件,
    其实目前成型的插件貌似没有几个。
    我还是喜欢自己做,
    把一些自己需要的功能模块化一下,用起来还顺手一些。

  18. 感觉好复杂。。。

  19. 试一下看看如何?

  20. 试一下看看如何

  21. 试一下看看如何

  22. 试一下看看如何

  23. 我也来看效果的.顺便学习了

  24. 提交测试下。。

  25. 这个回复能看到Ajax 提交评论的实现效果么?

  26. 我都是来看效果的

  27. 看看效果是否还在。

  28. 我是来看效果的

  29. 我是来看效果的

  30. 感谢你的网站, 终于完成了ajax留言

  31. 你是说绑定ctrl+enter?想不出什么情况下需要live绑定提交动作,提交按钮不是 一般初始加载上的吗?

  32. submit 好像不能用live绑定,很郁闷

  33. 测试测试~~

  34. @无冷
    国内土产,
    当然比较适合国情了,
    typecho很努力,
    但最近貌似冬眠了,
    有公司收购运作就猛了,
    很纳闷,心浪一直搞 sae 云计算,
    这么个好项目为啥不收购呢,
    对他的云平台使用率有很大的促进作用的,
    毕竟 sae 不是标准 php 环境,
    需要这么个玩意推广。

  35. @无冷
    基于2点没有加邮件回复
    1.怕被邮局spam掉我的邮箱。
    2.还要再调整评论提交的数据。
    回复给谁支持数组吗,我的评论回复可以同时回复多人。懒阿。

  36. XiangZi :@无冷
    还以为你博客主题是原生支持的呢,晕。

    回复引用这块有点蛋疼啊,可能会出现点不到啊, typecho是原生态支持ajax评论的

  37. @XiangZi 貌似你的主题没有邮件回复啊,
    另外可以加一个favicon.ico

  38. @无冷
    还以为你博客主题是原生支持的呢,晕。

  39. 这个代码有时间研究一下

  40. @卢松松
    移植出来,没这本事啊。

  41. 你要是能把它移植出来就更完美了

  42. @ymmcute
    还好

  43. 越来越厉害喽 人气越来越多哦!

  44. @wind
    难道是不难,还有许多要改进的地方,我也正在学习。

  45. 技术类啊
    没技术看到代码脑袋就迷糊- -!

  46. 又有新的效果了,有空试试。

  47. @皮鞋
    主要是针对某个主题的,
    有一个倒是比较通用,但效率较低。

  48. 这个分享很有价值,先存着,明天来琢磨一下子。

  49. @创意设计
    还好这些不算太难的。

  50. 看到代码我就头疼。

  51. @先看看
    谢谢,夸奖。

  52. 代码写的很好

  53. @梦无忧
    没问题
    @小开博客
    共同进步

  54. 翔子要是有什么好看好用的插件以后给我推荐下啊,代码现在还不怎么会弄呢!

  55. 过来学习 wp,呵呵。。。

  56. @贾学龙博客
    还是共同学习一下比较好

  57. 过来学习WP了