成航先森 成航先森

成都航院计算机系一个学生的个人博客

 

经验杂笔

分段图

最新文章

经验杂笔
当前位置: 首页 » 大学杂谈 » 经验杂笔 » 用cookie记住用户信息后ajax实现实时显示Gravatar头像并实时缓存到本地

用cookie记住用户信息后ajax实现实时显示Gravatar头像并实时缓存到本地

编辑:狂族晨曦 来源:经验杂笔 日期:2016-04-18 阅读: 2,063 次 7 条评论 » 百度已收录

首先说一点,本文的内容是先森研究了几天的成果,并且还导致了网站几天没有更新。

先森之前遇到了开启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

访问错误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文件中:

/*
*张戈博客原创
*成航先森修改
* http://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='http://img.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 = "http://img.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> &nbsp;<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&amp;&amp;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,但再次触发更换头像链接函数的时候,相关的头像已经被缓存成功就会显示出来了。先森目前没有想到解决的办法,所以最后有一个经过评论输入框的时候也会触发函数。这样增加触发,头像就能很好的显示出来了,目前先这样,等以后想到解决办法再说。

这样设置后的好处还有一点,就是默认头像始终都是你设置本地缓存中的那个默认头像。

标签:
除特别注明外,本站所有文章均为成航先森 www.capjsj.cn原创,本文共11352个字
转载请注明出处来自http://www.capjsj.cn/ycookiejzyhxxhsxssxsgravatartxbsshcdbd.html
已有 7 位"计工"发布了激烈的评论,还有N多人围观笑而不语评论
狂族晨曦的头像
欢迎发表评论
取消评论

表情
疑问调皮伤心抠鼻黑线微笑可爱奸笑震惊吓到了撇嘴大兵忍不住笑笑狂骂狂怒噢?鼓掌酷⊙﹏⊙b汗鄙视大哭嘿嘿

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. 破浪无忧Blog的头像

    非常不错!! :wink:

    2016-04-19 10:42 回复
  2. 小C博客的头像

    真的不错!!!

    2016-04-19 21:07 回复
  3. 我爱动感单车网的头像

    我所使用的“欲思1.0主题”,虽然原本也自带了头像缓存到本地功能,但发现代码乱七八糟一大堆、以及速度依然慢的很。很想换个好用的缓存到本地的方法,但限于自个技术小白一枚,一直没能实现,实在是纠结、郁闷啊!

    2016-10-18 12:38 回复
  4. 我爱动感单车网的头像

    :arrow: 对于我来说,实在是太复杂和工作量巨大,只能是望洋兴叹了!

    2016-10-18 15:56 回复
  5. 黑狼的头像
    黑狼:

    hi,大哥,您好,这几天看到你这篇教程也想学着改一下。依葫芦画瓢设置了一些,但是老是没有效果。可能有些ID没有设置好。不知道能否贴一份comment的form里html代码结构呢,这样可能更理解具体是如何操作的。多谢啊。

    2017-05-23 07:36 回复
    • 博主的Gravatar 头像

      @黑狼: 已经贴出来了,如果缓存还没有刷新,访问网页的时候在链接后面加?1234就可以看到最新更新的内容了。

      2017-05-23 16:42 回复
官方微信
发表评论 返回顶部