之所以要缓存gravatar头像,是为了加快速度,省略对gravatar.com的https请求,而之所以用https,是为了避免某反动势力的窥探。嗯,你们这些与全社会作对的,是历史的倒退,总有一天会颠覆在人民的汪洋大海中,毛主席的红色小卫兵们,冲啊!!
扯远了,回来。wordpress有些插件也是可以缓存gravatar头像的,但是因为科技的进步,这些久不更新的插件虽然勉强能用,但是总有些问题,甚至可能导致头像不显示,所以只好人肉写代码了。
其实是很简单的。wordpress显示头像是使用了 get_avatar 函数,这个函数在 /wp-include/pluggable.php 文件中,而查看源代码发现这个函数是返回了这么一个string
<img alt='{$safe_alt}' src='{$out}' class='avatar avatar-{$size} photo' height='{$size}' width='{$size}' />
所以只需要在主题文件的functions.php中添加一个filter,然后把src中的图片地址替换掉,改成自己服务器上图片的地址。
function my_get_avatar($text) {
preg_match('/https:\/\/secure.gravatar.com\/avatar\/([a-z0-9]+)\?s=(\d+)(?:\S*)&r=(\w*)/',$text,$match);
$ourl = $match[0];
$email_hash = $match[1];
$size = $match[2];
$rate = $match[3];
$ch = curl_init("http://en.gravatar.com/{$email_hash}.php");
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
curl_exec($ch);
$info = curl_getinfo($ch,CURLINFO_HTTP_CODE);
curl_close($ch);
if ( $info === 404 ) {
$url = '/wp-content/themes/gravatar/default_'.$size;
} else {
if ( empty($rate) ) {
$rate = "G";
}
$file = $_SERVER["DOCUMENT_ROOT"].'/wp-content/themes/gravatar/'.$email_hash.'_'.$size.'_'.$rate;
if ( !file_exists($file) ) {
$img = file_get_contents("https://secure.gravatar.com/avatar/{$email_hash}?s={$size}&d=mm");
file_put_contents($file,$img);
}
$url = '/wp-content/themes/gravatar/'.$email_hash.'_'.$size.'_'.$rate;
}
return preg_replace('/src=\'\S+\'/',"src='{$url}'",$text);
}
add_filter('get_avatar','my_get_avatar');
这个代码就是把get_avatar返回的string再传递给my_get_avatar,这时候就可以从这个string中找出头像图片的地址,从而提取出这个地址中包含的用户的email地址的md5 hash值和头像的大小以及分级。
然后用这个email的md5 hash值查看这个用户是否有gravatar头像,如果没有就直接使用默认的头像。否则就查看服务器上是不是已经有了缓存的图片,如果没有,那就去gravatar.com下载,如果有了就直接使用缓存的图片。最后用服务器上的图片的地址替换掉get_avatar函数输出的地址,再把这一整串替换过图片地址的<img xxx />作为结果返回。这时候wordpress再调用get_avatar函数时就会执行这个filter,图片地址就会自动替换了。
用的时候先建立图片储存的目录,/wp-content/themes/gravatar/ ,然后在里面放上默认头像,格式是 default_{$size} 。比如评论中的头像大小是32,那就放个 default_32 作为默认头像。因为默认头像并不会自动下载,所以要事先把需要用到的各个大小的默认头像都下载一份。然后如果某个有gravatar头像的新读者留言了,因为评论中的头像大小是32,于是就会下载相应的头像图片,并以格式 {$email_hash}_{$size}_{$rate} 存在服务器中,以后这个用户的头像就都会使用这个服务器中的副本了。
有个缺点是没有考虑到用户更换gravatar头像,所以可以做个cron任务,隔一段时间把 /wp-content/themes/gravatar/ 中除了默认头像的所有文件删除。另一个缺点是如果用户的gravatar帐号绑定了多个email,而用户留言用的不是主email,那么就无法显示他的头像了。因为在判断用户是否有gravatar头像的时候,只要不是主email都会返回的是没有头像,这其实是gravatar提供的用来判断用户是否存在的api的限制。
Update 2013-01-31:
做了个插件版:传送门
谢谢你 试试看这个代码效率如何