上次排查完”评论时间全站同一个”之后,我顺手把评论区从头到尾看了一遍,又揪出一个毛病:所有评论者的头像都是裂图——一个破图标识,或者干脆空白一片。
这个问题在国内 WordPress 站长里非常普遍,但很多人的处理方式是装插件。其实不用,十几行代码就能彻底解决。今天把排查思路、完整代码和逐行解释都写下来。

排查顺序很简单,三步:
https://secure.gravatar.com/avatar/xxxxx?s=96&d=mm&r=g 这种形式,头像来自第三方服务 Gravatar(WordPress 官方的全球头像服务);既然是”源头取不到”,那思路就很直接:WordPress 把头像地址吐出来之前,把域名换成国内能访问的镜像。头像数据还是在 Gravatar 那儿,只是取道一条能通的网络。
这里用到 WordPress 一个非常核心的机制——过滤器(Filter):WordPress 在输出头像时会先发出一个get_avatar钩子,允许我们在真正输出之前插一手、把内容改掉。所以不用改核心文件、不用动数据库、不影响后面的升级。
把下面这段代码加到当前主题(或者子主题)的 functions.php 文件末尾,<?php 之后即可:
/**
* 修复 Gravatar 头像国内无法加载(裂图)的问题
* 原理:WordPress 输出头像前,把域名替换为国内可访问的镜像
*/
function liu_replace_gravatar( $avatar ) {
$avatar = str_replace(
array(
'www.gravatar.com',
'0.gravatar.com',
'1.gravatar.com',
'2.gravatar.com',
'secure.gravatar.com',
'cn.gravatar.com',
),
'cravatar.cn',
$avatar
);
return $avatar;
}
add_filter( 'get_avatar', 'liu_replace_gravatar' );
add_filter( 'get_avatar', 'liu_replace_gravatar' ); 是整段代码的关键。它的意思是:告诉 WordPress,以后每次要输出头像(钩子 get_avatar),都先把头像内容交给 liu_replace_gravatar 这个函数处理一遍,用处理后的结果再去显示。
好处是零侵入:WordPress 核心、主题模板、评论数据,一个字节都不用改。
很多人只写 str_replace('www.gravatar.com', ...),结果还是有人的头像裂。因为 Gravatar 实际会返回好几种域名:secure.gravatar.com(最常用)、带数字前缀的 0/1/2.gravatar.com(负载均衡用)、甚至有的版本会返回 cn.gravatar.com。用数组一次性把可能出现的情况全列上,才不会漏。
这里有个容易踩的点:get_avatar 钩子传进来的 $avatar,不是图片 URL,而是一整段已经拼好的 HTML(形如 <img alt='' src='https://...' class='avatar avatar-96' />)。因此直接对整段字符串做替换即可,不用去解析 src 属性,简单可靠。
return $avatar; 这一行看着最不起眼,却是最容易翻车的地方。过滤器的约定是:拿到值、加工、必须还回去。如果忘了 return,函数返回空,所有头像就会整个消失——比裂图还糟。
主题的 functions.php 是放自定义功能的标准位置,随主题加载、不用额外配置。但有个坑要提醒:换主题就失效。如果以后打算换主题或者更新主题,更稳妥的做法是使用子主题,或者用代码片段类插件来托管这类自定义代码。
我另一个站(二级域名站)的头像不是裂图,而是全站几百个用户长着同一张脸。查下来的原因是:早年用过一个”WP User Avatar”插件,插件早就删了,但后台「设置 → 讨论 → 默认头像」还残留着指向该插件的选项,一旦 Gravatar 取不到头像,所有人就都顶着那一张默认图。
治法同样是零代码:进后台「设置 → 讨论 → 头像」区块,把默认头像重新选成 WordPress 自带的标准选项就行了。
两个站、两种现象,实际是同一个根因的两个面:Gravatar 在国内取不到——一个是连不上(裂图),一个是连不上后的兜底兜错了(万人一脸)。
这次和上次的”评论时间”问题其实是同一类:看着像 WordPress 坏了,实际是某个环节取不到数据或者格式办错了。找准那个环节,改起来往往比想象中简单——这次从头到尾就是一段 str_replace,一个安装过程都不需要。