用cookie记住用户信息后ajax实现实时显示Gravatar头像并实时缓存到本地
编辑:狂族晨曦 来源:经验杂笔 日期:2016-04-18 阅读: 4,378 次 9 条评论 » 百度已收录
首先说一点,本文的内容是先森研究了几天的成果,并且还导致了网站几天没有更新。
先森之前遇到了开启CDN后网站会连先森登录之后的显示样式一起缓存的问题。想想还是很危险的,要是文章页第一次是被已知用户访问,那么其他所有人访问后就是他看到的样子,那样说不定连他的邮箱地址都被暴露了。
这个问题很容易解决,通过张戈博客的cookie记住用户信息的方法,再加上让所有人访问网站都是未登录状态,这个问题就OK了。再加上一些优化用户体验的操作,也没有花先森多少时间,但是gravatar头像的事情,却一直横在了先森心中,先森的强迫症就又犯了。
关于过往研究的历程,先森已经分享过了,如果没有看的最好可以去看看,本文是建在之前的基础之上的:
预期效果
先森想实现的显示Gravatar的方式,并不是简单的用多说或者Gravatar中国的服务器的那种。先森之前就用的是将头像本地缓存,用以提高加载速度。
所以先森想实现的是:
1.用户是已知用户的时候,页面打开时自动加载缓存在本地服务器的其邮箱对应的Gravatar头像。
2.如果用户修改或填写邮箱的时候,则自动将其对应的Gravatar缓存到本地服务器,再显示出来。
如果服务器不使用本地服务器的话,上面的两条很容易实现。因为不用缓存,而Gravatar的头像链接又是固定的http://www.gravatar.com/avatar/xxxx(xxxx为邮箱的md5加密值),只要获取到邮箱,将邮箱通过哈希算法变为md5加密值,将这段MD5值填入链接中,就是用户的头像了。但难就难在先森想要将头像同时本地缓存。
不过,经过几天的努力,绕了很大的圈子,总算是搞定了。
效果实现
相信很多WordPress站长的评论源代码,是由comments.php、comments-ajax.php、comments-ajax.js三个文件构成。如果是则很会很方便,不是也没有多大差别。
1.将Gravatar头像缓存到本地服务器
这个教程早就已经烂大街了,为了本文内容先森不得不重提一遍。为什么要缓存到本地服务器?
因为Gravatar是国外服务器的,很容易被墙,且容易访问超时,导致网页加载速度变慢。缓存到本地服务器就可以有效的解决这个尴尬。当然,你也可以直接把头像缓存到七牛云储存,也就没有本文这么麻烦了。为什么先森要选择麻烦的方法?爱折腾呗~
将Gravatar头像缓存到本地服务器的方法就是,在你的functions.php中加入以下代码:
//本地缓存gravatar头像 function fa_cache_avatar($avatar, $id_or_email, $size, $default, $alt) { $avatar = str_replace(array("www.gravatar.com", "0.gravatar.com", "1.gravatar.com", "2.gravatar.com"), "gravatar.duoshuo.com", $avatar); $tmp = strpos($avatar, 'http'); $url = get_avatar_url( $id_or_email, $size ) ; $url = str_replace(array("www.gravatar.com", "0.gravatar.com", "1.gravatar.com", "2.gravatar.com"), "gravatar.duoshuo.com", $url); $avatar2x = get_avatar_url( $id_or_email, ( $size * 2 ) ) ; $avatar2x = str_replace(array("www.gravatar.com", "0.gravatar.com", "1.gravatar.com", "2.gravatar.com"), "gravatar.duoshuo.com", $avatar2x); $g = substr($avatar, $tmp, strpos($avatar, "'", $tmp) - $tmp); $tmp = strpos($g, 'avatar/') + 7; $f = substr($g, $tmp, strpos($g, "?", $tmp) - $tmp); $w = home_url(); $e = ABSPATH .'avatar/'. $size . '*'. $f .'.jpg'; $e2x = ABSPATH .'avatar/'. ( $size * 2 ) . '*'. $f .'.jpg'; $t = 1209600; //缓存更新时间 if ( (!is_file($e) || (time() - filemtime($e)) > $t) && (!is_file($e2x) || (time() - filemtime($e2x)) > $t ) ) { copy(htmlspecialchars_decode($g), $e); copy(htmlspecialchars_decode($avatar2x), $e2x); } else { $avatar = $w.'/avatar/'. $size . '*'.$f.'.jpg'; $avatar2x = $w.'/avatar/'. ( $size * 2) . '*'.$f.'.jpg'; if (filesize($e) < 1000) copy($w.'/avatar/default.jpg', $e); if (filesize($e2x) < 1000) copy($w.'/avatar/default.jpg', $e2x); $avatar = "<img alt='{$alt}' src='{$avatar}' srcset='{$avatar2x}' class='avatar avatar-{$size} photo' id='real-time-gravatar' height='{$size}' width='{$size}' />"; } return $avatar; } add_filter('get_avatar', 'fa_cache_avatar',1,5);
如果你的网站已经实现则忽略,没有的话就先添加备用。
2.新建gravatar.php
上面的代码是修改了WordPress的get_acatar函数。而我们想要实时的缓存Gravatar邮箱,则需要将邮箱的MD5值传递给get_acatar函数。上面的代码最后会有输出,而我们并不需要它的输出,只要它将头像缓存即可。
所以我们需要新建一个gravatar.php文件,将ajax传递过来的邮箱MD5值接收,并让get_acatar函数将对应的头像缓存。gravatar.php的代码如下:
<?php //缓存头像 if ( 'POST' != $_SERVER['REQUEST_METHOD'] ) { header('Allow: POST'); header('HTTP/1.1 405 Method Not Allowed'); header('Content-Type: text/plain'); echo "请不要直接访问该页面"; exit; } require( dirname(__FILE__) . '/../../../wp-load.php' );//使用 WordPress自带函数进行数据提交 $email = $_POST['email'];//获取邮箱md5值 get_avatar( $email, $size = '48' ); //将头像缓存 ?>
其中,下面这段代码很重要:
require( dirname(__FILE__) . '/../../../wp-load.php' );
如果不加上的话会导致数据存入失败,POST访问也会返回错误500。这也是挡住了先森研究很久的一个问题。之前代码中之后最后的两句,获取和缓存,结果一直显示不成功。
访问错误500
后来在百度找原因一直没找到,却意外看到了一篇写用ajax提交评论的优点的文章中有一句“使用wordpress自带的admin-ajax.php进行数据提交”,先森感觉脑子一炸,将comments-ajax.php中一句不起眼的代码(即上面那句)复制过来。一尝试。OK返回成功。
3.ajax动态刷新
ajax是一种在不刷新整个页面,与服务器实现数据交换的网页开发技术。
这个技术被称为称为“艺术”,但先森是不懂艺术的,所以这几天花的最多的时间就是在这里了。先森还专门跑去w3school学了一下ajax方面的教程,结果也没懂个啥,仅仅是对概念更清楚了些。
这个技术在本文的担当是,动态的将邮箱md5值提交给服务器,服务器将头像缓存。
我们的ajax代码,可以加入到comments-ajax.js中,也可以自己新建一个js文件。
首先,我们需要将Gravater邮箱地址变换为MD5值,需要用到一串复杂的算法,将以下代码加入js中:
因为比较长,所以提供下载,不直接将代码贴出来了。
接下来将下面的代码加入comments-ajax.js或你准备好的js文件中:
/* *张戈博客原创 *成航先森修改 * //www.capjsj.cn/ycookiejzyhxxhsxssxsgravatartxbsshcdbd.html */ var Umail = decodeURIComponent(GetCookie('email'));//通过cookie获取用户邮箱,并解码 var Uname = decodeURIComponent(GetCookie('author')); var Umail_md5 = ""; if (Umail != "null" && Umail != "" && Umail != null) {//如果邮箱有内容,则赋值 var Umail_md5 = hex_md5(Umail); } if (Umail_md5 != "" && Umail_md5 != null && Umail_md5 != "null") {//如果邮箱哈希后存在内容 jQuery(document).ready(function($) { jQuery('#comment-author-info').hide();//隐藏信息填写框 }); /*下面的real-avatar是包裹着头像的div*/ document.getElementById('real-avatar').innerHTML = "<img src='//cos.capjsj.cn/avatar/96*" + Umail_md5 + ".jpg' width='48' height='48' alt='avatar' class='avatar avatar-48 photo' id='real-time-gravatar'>"; var changeMsg = '修改信息'; var closeMsg = '关闭'; function toggleCommentAuthorInfo() { jQuery('#comment-author-info').slideToggle('slow', function() { if (jQuery('#comment-author-info').css('display') == 'none') {//如果信息填写框被隐藏 jQuery('.switch-author').text(changeMsg);//改变标签内容为“修改信息” } else { jQuery('.switch-author').text(closeMsg);//改变标签内容为"关闭" } }); } } var gar_img = document.getElementById("real-time-gravatar");/*头像img标签*/ var U_email = document.getElementById("email"); var textarea = document.getElementById("comment");/*评论输入框*/ var KaK = navigator.userAgent.toLowerCase();/*获取浏览器信息*/ var chrome = KaK.indexOf('webkit') != -1; function changeGravatar() { email_value = U_email.value; email_md5 = hex_md5(email_value); php_url=js_url.replace('comments-ajax.js','gravatar.php');//替换js链接中的文件名 $.ajax({ type:'POST', data:{ "email": email_value, }, //ajax对象文件:gavater.php url:php_url, cache: false, }); new_ga = "//cos.capjsj.cn/avatar/48*" + email_md5 +".jpg"; newGravatar(new_ga);/*启动下面的脚本*/ }; function newGravatar(new_ga) { gar_img.setAttribute('src', new_ga);/*将图片链接换成新的链接*/ }; if (chrome) { U_email.onblur = changeGravatar;/*鼠标离开输入框时执行 JavaScript 代码*/ } else { U_email.onchange = changeGravatar;/*在内容改变的时候执行*/ }; textarea.onmouseover = changeGravatar;/*在鼠标指针移动到元素上时触发行 JavaScript 代码
代码是从张戈博客那里扒来的,因为张戈实现的是Nginx自动将Gravatar头像本地缓存,所以他不用担心先森的这种缓存问题。所以先森将张哥的代码稍作修改,增加了ajax代码,既可以满足先森的要求了。
上面的代码中,ajax代码是下面这串:
$.ajax({ type:'POST', data:{ "email": email_value, }, //ajax对象文件:gavater.php url:php_url, cache: false, });
如果你需要调试,可以将代码缓存下面这样,根据弹窗信息确认是否成功:
$.ajax({ type:'POST', data:{ "email": email_value, }, //ajax对象文件:gavater.php url:php_url, cache: false, error: function(){ alert('发生意外错误!'); //弹窗显示 return false; }, success:function(){ alert('缓存成功'); } });
应网友要求,先贴出comments.php中form标签的内容,以供参考。
<form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform"> <div class="comt-title" id="comt-title"> <div class="comt-avatar pull-left" id="real-avatar"> <?php //输入评论上的头像 global $current_user; get_currentuserinfo(); if ( is_user_logged_in() ) //$current_user->user_email获取邮箱 echo get_avatar( $current_user->user_email, $size = '48' ,'');//如果是管理员 elseif( !is_user_logged_in() && get_option('require_name_email') && $comment_author_email=='' ) echo get_avatar( $current_user->user_email, $size = '48','');//没有登录,但是是已知用户 elseif( !is_user_logged_in() && get_option('require_name_email') && $comment_author_email!=='' ) echo get_avatar( $comment->comment_author_email, $size = '48','');//, $touxiang else echo get_avatar( $comment->comment_author_email, $size = '48' ,'');//, $touxiang ?> </div> <div class="comt-author" id="switch-author"> <?php if ( is_user_logged_in() ) {//判断登录 printf('<b id="nickname">'.$user_identity.'</b><span>发表我的评论</span>'); }else{ if( get_option('require_name_email') && !empty($comment_author_email) ){//如果没登录,但是是已知用户 printf('<b id="nickname">'.$comment_author.'</b><span>欢迎回来</span> <b>【<a class="switch-author" href="javascript:toggleCommentAuthorInfo();" data-type="switch-author" style="font-size:15px;">修改信息</a>】</b>'); }else{//如果是未知用户 printf('<b id="nickname"></b><span id="huilai">欢迎发表评论</span>'); } } ?> <?php //如果关闭了WP Super Cache中的让已知用户匿名,则要删除下面的<b>标签?> <b id="switch-author" style="display:none">【<a class="switch-author" href="javascript:;" data-type="switch-author" style="font-size:15px;">修改信息</a>】</b> </div> <a id="cancel-comment-reply-link" class="pull-right" href="javascript:;">取消评论</a> </div> <div class="comt"> <div class="comt-box"> <textarea placeholder="说点什么吧,您的回复是对先森最大的支持!" class="input-block-level comt-area" name="comment" id="comment" cols="50%" rows="3" tabindex="1" onkeydown="if(event.ctrlKey&&event.keyCode==13){document.getElementById('submit').click();return false};"></textarea> <div class="comt-ctrl"> <button class="btn btn-primary pull-right" type="submit" name="submit" id="submit" tabindex="5"><i class="fa fa-check-square-o"></i> 提交评论</button> <div class="comt-tips pull-right"><?php comment_id_fields(); do_action('comment_form', $post->ID); ?></div> <span class="muted comt-mailme"><?php deel_add_checkbox() ?></span> <span data-type="comment-insert-smilie" class="muted comt-smilie"><i class="fa fa-smile-o"></i> 表情</span> <div id="comment-smilies" class="hide" style="display:"><?php include(TEMPLATEPATH . '/smiley.php'); ?></div> </div> </div> <?php if ( !is_user_logged_in() ) { ?> <?php if( get_option('require_name_email') ){ ?> <div class="comt-comterinfo" id="comment-author-info"<?php if ( !empty($comment_author) ) echo 'style="display:none"';else echo 'style="display:block"'; ?>> <h4>Hi,您需要填写昵称和邮箱!</h4> <ul> <li class="form-inline"><label class="hide" for="author">昵称</label><input class="ipt" type="text" name="author" id="author" value="<?php echo esc_attr($comment_author); ?>" tabindex="2" placeholder="昵称"><span class="help-inline">昵称 (必填)</span></li> <li class="form-inline"><label class="hide" for="email">邮箱</label><input class="ipt" type="text" name="email" id="email" value="<?php echo esc_attr($comment_author_email); ?>" tabindex="3" placeholder="邮箱"><span class="help-inline">邮箱 (必填)</span></li> <li class="form-inline"><label class="hide" for="url">网址</label><input class="ipt" type="text" name="url" id="url" value="<?php echo esc_attr($comment_author_url); ?>" tabindex="4" placeholder="网址"><span class="help-inline">网址</span></li> </ul> </div> <?php } ?> <?php } ?> </div> </form>
总结
文中的代码涉及到了很多标签的ID,请参考本站的设置情况进行对应修改。
因为代码逐行执行的速度比服务器缓存的速度快,所以当刚修改邮箱的时候,可能图片会显示404,但再次触发更换头像链接函数的时候,相关的头像已经被缓存成功就会显示出来了。先森目前没有想到解决的办法,所以最后有一个经过评论输入框的时候也会触发函数。这样增加触发,头像就能很好的显示出来了,目前先这样,等以后想到解决办法再说。
这样设置后的好处还有一点,就是默认头像始终都是你设置本地缓存中的那个默认头像。
转载请注明出处来自https://www.capjsj.cn/ycookiejzyhxxhsxssxsgravatartxbsshcdbd.html
非常不错!!
@破浪无忧Blog: 嘿嘿,谢谢支持~
真的不错!!!
我所使用的“欲思1.0主题”,虽然原本也自带了头像缓存到本地功能,但发现代码乱七八糟一大堆、以及速度依然慢的很。很想换个好用的缓存到本地的方法,但限于自个技术小白一枚,一直没能实现,实在是纠结、郁闷啊!
hi,大哥,您好,这几天看到你这篇教程也想学着改一下。依葫芦画瓢设置了一些,但是老是没有效果。可能有些ID没有设置好。不知道能否贴一份comment的form里html代码结构呢,这样可能更理解具体是如何操作的。多谢啊。
@黑狼: 已经贴出来了,如果缓存还没有刷新,访问网页的时候在链接后面加?1234就可以看到最新更新的内容了。
辛苦博主了
学习了,顺利巴拉使用上了。