用cookie記住用戶(hù)信息后ajax實(shí)現(xiàn)實(shí)時(shí)顯示Gravatar頭像并實(shí)時(shí)緩存到本地
編輯:狂族晨曦 來(lái)源:經(jīng)驗(yàn)雜筆 日期:2016-04-18 閱讀: 4,732 次 9 條評(píng)論 » 百度已收錄
首先說(shuō)一點(diǎn),本文的內(nèi)容是先森研究了幾天的成果,并且還導(dǎo)致了網(wǎng)站幾天沒(méi)有更新。
先森之前遇到了開(kāi)啟CDN后網(wǎng)站會(huì)連先森登錄之后的顯示樣式一起緩存的問(wèn)題。想想還是很危險(xiǎn)的,要是文章頁(yè)第一次是被已知用戶(hù)訪問(wèn),那么其他所有人訪問(wèn)后就是他看到的樣子,那樣說(shuō)不定連他的郵箱地址都被暴露了。
這個(gè)問(wèn)題很容易解決,通過(guò)張戈博客的cookie記住用戶(hù)信息的方法,再加上讓所有人訪問(wèn)網(wǎng)站都是未登錄狀態(tài),這個(gè)問(wèn)題就OK了。再加上一些優(yōu)化用戶(hù)體驗(yàn)的操作,也沒(méi)有花先森多少時(shí)間,但是gravatar頭像的事情,卻一直橫在了先森心中,先森的強(qiáng)迫癥就又犯了。
關(guān)于過(guò)往研究的歷程,先森已經(jīng)分享過(guò)了,如果沒(méi)有看的最好可以去看看,本文是建在之前的基礎(chǔ)之上的:
預(yù)期效果
先森想實(shí)現(xiàn)的顯示Gravatar的方式,并不是簡(jiǎn)單的用多說(shuō)或者Gravatar中國(guó)的服務(wù)器的那種。先森之前就用的是將頭像本地緩存,用以提高加載速度。
所以先森想實(shí)現(xiàn)的是:
1.用戶(hù)是已知用戶(hù)的時(shí)候,頁(yè)面打開(kāi)時(shí)自動(dòng)加載緩存在本地服務(wù)器的其郵箱對(duì)應(yīng)的Gravatar頭像。
2.如果用戶(hù)修改或填寫(xiě)郵箱的時(shí)候,則自動(dòng)將其對(duì)應(yīng)的Gravatar緩存到本地服務(wù)器,再顯示出來(lái)。
如果服務(wù)器不使用本地服務(wù)器的話,上面的兩條很容易實(shí)現(xiàn)。因?yàn)椴挥镁彺妫鳪ravatar的頭像鏈接又是固定的http://www.gravatar.com/avatar/xxxx(xxxx為郵箱的md5加密值),只要獲取到郵箱,將郵箱通過(guò)哈希算法變?yōu)閙d5加密值,將這段MD5值填入鏈接中,就是用戶(hù)的頭像了。但難就難在先森想要將頭像同時(shí)本地緩存。
不過(guò),經(jīng)過(guò)幾天的努力,繞了很大的圈子,總算是搞定了。
效果實(shí)現(xiàn)
相信很多WordPress站長(zhǎng)的評(píng)論源代碼,是由comments.php、comments-ajax.php、comments-ajax.js三個(gè)文件構(gòu)成。如果是則很會(huì)很方便,不是也沒(méi)有多大差別。
1.將Gravatar頭像緩存到本地服務(wù)器
這個(gè)教程早就已經(jīng)爛大街了,為了本文內(nèi)容先森不得不重提一遍。為什么要緩存到本地服務(wù)器?
因?yàn)镚ravatar是國(guó)外服務(wù)器的,很容易被墻,且容易訪問(wèn)超時(shí),導(dǎo)致網(wǎng)頁(yè)加載速度變慢。緩存到本地服務(wù)器就可以有效的解決這個(gè)尷尬。當(dāng)然,你也可以直接把頭像緩存到七牛云儲(chǔ)存,也就沒(méi)有本文這么麻煩了。為什么先森要選擇麻煩的方法?愛(ài)折騰唄~
將Gravatar頭像緩存到本地服務(wù)器的方法就是,在你的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; //緩存更新時(shí)間
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);
如果你的網(wǎng)站已經(jīng)實(shí)現(xiàn)則忽略,沒(méi)有的話就先添加備用。
2.新建gravatar.php
上面的代碼是修改了WordPress的get_acatar函數(shù)。而我們想要實(shí)時(shí)的緩存Gravatar郵箱,則需要將郵箱的MD5值傳遞給get_acatar函數(shù)。上面的代碼最后會(huì)有輸出,而我們并不需要它的輸出,只要它將頭像緩存即可。
所以我們需要新建一個(gè)gravatar.php文件,將ajax傳遞過(guò)來(lái)的郵箱MD5值接收,并讓get_acatar函數(shù)將對(duì)應(yīng)的頭像緩存。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 "請(qǐng)不要直接訪問(wèn)該頁(yè)面";
exit;
}
require( dirname(__FILE__) . '/../../../wp-load.php' );//使用 WordPress自帶函數(shù)進(jìn)行數(shù)據(jù)提交
$email = $_POST['email'];//獲取郵箱md5值
get_avatar( $email, $size = '48' ); //將頭像緩存
?>
其中,下面這段代碼很重要:
require( dirname(__FILE__) . '/../../../wp-load.php' );
如果不加上的話會(huì)導(dǎo)致數(shù)據(jù)存入失敗,POST訪問(wèn)也會(huì)返回錯(cuò)誤500。這也是擋住了先森研究很久的一個(gè)問(wèn)題。之前代碼中之后最后的兩句,獲取和緩存,結(jié)果一直顯示不成功。

訪問(wèn)錯(cuò)誤500
后來(lái)在百度找原因一直沒(méi)找到,卻意外看到了一篇寫(xiě)用ajax提交評(píng)論的優(yōu)點(diǎn)的文章中有一句“使用wordpress自帶的admin-ajax.php進(jìn)行數(shù)據(jù)提交”,先森感覺(jué)腦子一炸,將comments-ajax.php中一句不起眼的代碼(即上面那句)復(fù)制過(guò)來(lái)。一嘗試。OK返回成功。
3.ajax動(dòng)態(tài)刷新
ajax是一種在不刷新整個(gè)頁(yè)面,與服務(wù)器實(shí)現(xiàn)數(shù)據(jù)交換的網(wǎng)頁(yè)開(kāi)發(fā)技術(shù)。
這個(gè)技術(shù)被稱(chēng)為稱(chēng)為“藝術(shù)”,但先森是不懂藝術(shù)的,所以這幾天花的最多的時(shí)間就是在這里了。先森還專(zhuān)門(mén)跑去w3school學(xué)了一下ajax方面的教程,結(jié)果也沒(méi)懂個(gè)啥,僅僅是對(duì)概念更清楚了些。
這個(gè)技術(shù)在本文的擔(dān)當(dāng)是,動(dòng)態(tài)的將郵箱md5值提交給服務(wù)器,服務(wù)器將頭像緩存。
我們的ajax代碼,可以加入到comments-ajax.js中,也可以自己新建一個(gè)js文件。
首先,我們需要將Gravater郵箱地址變換為MD5值,需要用到一串復(fù)雜的算法,將以下代碼加入js中:
因?yàn)楸容^長(zhǎng),所以提供下載,不直接將代碼貼出來(lái)了。
接下來(lái)將下面的代碼加入comments-ajax.js或你準(zhǔn)備好的js文件中:
/*
*張戈博客原創(chuàng)
*成航先森修改
* //www.cnidcc.cn/ycookiejzyhxxhsxssxsgravatartxbsshcdbd.html ?
*/
var Umail = decodeURIComponent(GetCookie('email'));//通過(guò)cookie獲取用戶(hù)郵箱,并解碼
var Uname = decodeURIComponent(GetCookie('author'));
var Umail_md5 = "";
if (Umail != "null" && Umail != "" && Umail != null) {//如果郵箱有內(nèi)容,則賦值
var Umail_md5 = hex_md5(Umail);
}
if (Umail_md5 != "" && Umail_md5 != null && Umail_md5 != "null") {//如果郵箱哈希后存在內(nèi)容
jQuery(document).ready(function($) {
jQuery('#comment-author-info').hide();//隱藏信息填寫(xiě)框
});
/*下面的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 = '關(guān)閉';
function toggleCommentAuthorInfo() {
jQuery('#comment-author-info').slideToggle('slow', function() {
if (jQuery('#comment-author-info').css('display') == 'none') {//如果信息填寫(xiě)框被隱藏
jQuery('.switch-author').text(changeMsg);//改變標(biāo)簽內(nèi)容為“修改信息”
} else {
jQuery('.switch-author').text(closeMsg);//改變標(biāo)簽內(nèi)容為"關(guān)閉"
}
});
}
}
var gar_img = document.getElementById("real-time-gravatar");/*頭像img標(biāo)簽*/
var U_email = document.getElementById("email");
var textarea = document.getElementById("comment");/*評(píng)論輸入框*/
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對(duì)象文件:gavater.php
url:php_url,
cache: false,
});
new_ga = "//cos.capjsj.cn/avatar/48*" + email_md5 +".jpg";
newGravatar(new_ga);/*啟動(dòng)下面的腳本*/
};
function newGravatar(new_ga) {
gar_img.setAttribute('src', new_ga);/*將圖片鏈接換成新的鏈接*/
};
if (chrome) {
U_email.onblur = changeGravatar;/*鼠標(biāo)離開(kāi)輸入框時(shí)執(zhí)行 JavaScript 代碼*/
} else {
U_email.onchange = changeGravatar;/*在內(nèi)容改變的時(shí)候執(zhí)行*/
};
textarea.onmouseover = changeGravatar;/*在鼠標(biāo)指針移動(dòng)到元素上時(shí)觸發(fā)行 JavaScript 代碼
代碼是從張戈博客那里扒來(lái)的,因?yàn)閺埜陮?shí)現(xiàn)的是Nginx自動(dòng)將Gravatar頭像本地緩存,所以他不用擔(dān)心先森的這種緩存問(wèn)題。所以先森將張哥的代碼稍作修改,增加了ajax代碼,既可以滿足先森的要求了。
上面的代碼中,ajax代碼是下面這串:
$.ajax({
type:'POST',
data:{
"email": email_value,
},
//ajax對(duì)象文件:gavater.php
url:php_url,
cache: false,
});
如果你需要調(diào)試,可以將代碼緩存下面這樣,根據(jù)彈窗信息確認(rèn)是否成功:
$.ajax({
type:'POST',
data:{
"email": email_value,
},
//ajax對(duì)象文件:gavater.php
url:php_url,
cache: false,
error: function(){
alert('發(fā)生意外錯(cuò)誤!'); //彈窗顯示
return false;
},
success:function(){
alert('緩存成功');
}
});
應(yīng)網(wǎng)友要求,先貼出comments.php中form標(biāo)簽的內(nèi)容,以供參考。
<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 //輸入評(píng)論上的頭像
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','');//沒(méi)有登錄,但是是已知用戶(hù)
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>發(fā)表我的評(píng)論</span>');
}else{
if( get_option('require_name_email') && !empty($comment_author_email) ){//如果沒(méi)登錄,但是是已知用戶(hù)
printf('<b id="nickname">'.$comment_author.'</b><span>歡迎回來(lái)</span> <b>【<a class="switch-author" href="javascript:toggleCommentAuthorInfo();" data-type="switch-author" style="font-size:15px;">修改信息</a>】</b>');
}else{//如果是未知用戶(hù)
printf('<b id="nickname"></b><span id="huilai">歡迎發(fā)表評(píng)論</span>');
}
}
?>
<?php //如果關(guān)閉了WP Super Cache中的讓已知用戶(hù)匿名,則要?jiǎng)h除下面的<b>標(biāo)簽?>
<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:;">取消評(píng)論</a>
</div>
<div class="comt">
<div class="comt-box">
<textarea placeholder="說(shuō)點(diǎn)什么吧,您的回復(fù)是對(duì)先森最大的支持!" 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> 提交評(píng)論</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,您需要填寫(xiě)昵稱(chēng)和郵箱!</h4>
<ul>
<li class="form-inline"><label class="hide" for="author">昵稱(chēng)</label><input class="ipt" type="text" name="author" id="author" value="<?php echo esc_attr($comment_author); ?>" tabindex="2" placeholder="昵稱(chēng)"><span class="help-inline">昵稱(chēng) (必填)</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">網(wǎng)址</label><input class="ipt" type="text" name="url" id="url" value="<?php echo esc_attr($comment_author_url); ?>" tabindex="4" placeholder="網(wǎng)址"><span class="help-inline">網(wǎng)址</span></li>
</ul>
</div>
<?php } ?>
<?php } ?>
</div>
</form>
總結(jié)
文中的代碼涉及到了很多標(biāo)簽的ID,請(qǐng)參考本站的設(shè)置情況進(jìn)行對(duì)應(yīng)修改。
因?yàn)榇a逐行執(zhí)行的速度比服務(wù)器緩存的速度快,所以當(dāng)剛修改郵箱的時(shí)候,可能圖片會(huì)顯示404,但再次觸發(fā)更換頭像鏈接函數(shù)的時(shí)候,相關(guān)的頭像已經(jīng)被緩存成功就會(huì)顯示出來(lái)了。先森目前沒(méi)有想到解決的辦法,所以最后有一個(gè)經(jīng)過(guò)評(píng)論輸入框的時(shí)候也會(huì)觸發(fā)函數(shù)。這樣增加觸發(fā),頭像就能很好的顯示出來(lái)了,目前先這樣,等以后想到解決辦法再說(shuō)。
這樣設(shè)置后的好處還有一點(diǎn),就是默認(rèn)頭像始終都是你設(shè)置本地緩存中的那個(gè)默認(rèn)頭像。
轉(zhuǎn)載請(qǐng)注明出處來(lái)自http://www.cnidcc.cn/ycookiejzyhxxhsxssxsgravatartxbsshcdbd.html

川公網(wǎng)安備 51011202000104號(hào)
非常不錯(cuò)!!
@破浪無(wú)憂Blog: 嘿嘿,謝謝支持~
真的不錯(cuò)!!!
我所使用的“欲思1.0主題”,雖然原本也自帶了頭像緩存到本地功能,但發(fā)現(xiàn)代碼亂七八糟一大堆、以及速度依然慢的很。很想換個(gè)好用的緩存到本地的方法,但限于自個(gè)技術(shù)小白一枚,一直沒(méi)能實(shí)現(xiàn),實(shí)在是糾結(jié)、郁悶啊!
hi,大哥,您好,這幾天看到你這篇教程也想學(xué)著改一下。依葫蘆畫(huà)瓢設(shè)置了一些,但是老是沒(méi)有效果。可能有些ID沒(méi)有設(shè)置好。不知道能否貼一份comment的form里html代碼結(jié)構(gòu)呢,這樣可能更理解具體是如何操作的。多謝啊。
@黑狼: 已經(jīng)貼出來(lái)了,如果緩存還沒(méi)有刷新,訪問(wèn)網(wǎng)頁(yè)的時(shí)候在鏈接后面加?1234就可以看到最新更新的內(nèi)容了。
辛苦博主了
學(xué)習(xí)了,順利巴拉使用上了。