Yii 2.0.54 配置 ETag 需使用 yii\filters\HttpCache 过滤器并设置 callable 类型的 etagSeed,确保其返回稳定字符串以生成强校验哈希,仅对 GET/HEAD 请求生效,且需关闭调试模式、避免动态内容干扰响应体。

给 Yii 2.0.54 配置 HTTP 缓存的 ETag,核心是使用 yii\filters\HttpCache 过滤器,并正确设置 etagSeed 属性。ETag 不是直接设一个固定值,而是提供一个“种子”,Yii 会基于它生成强校验哈希(默认用 sha256),并在客户端发起 If-None-Match 请求时自动比对。
确保只对 GET/HEAD 请求生效
HttpCache 默认仅处理 GET 和 HEAD 方法。如果你的 action 接收 POST 或其他方法,ETag 不会参与校验,也不会返回 304。无需额外配置,但需确认请求方式符合预期。
在控制器中配置 etagSeed 回调
etagSeed 必须是一个 callable,返回字符串类型的稳定种子。关键原则是:只要响应内容不变,种子就必须完全一致;内容一变,种子就应变化。常见安全写法包括:
- 用版本号或构建标识,如
return 'v2.1.0'; - 用关键数据的哈希,如
return md5($post->title . $post->content);(需确保变量已加载) - 用数据库记录的更新时间戳拼接,如
return $post->updated_at . '-' . $post->id; - 避免使用
time()、microtime()、uniqid()等动态值,否则每次 ETag 都不同,304 永远不触发
禁用调试模式(YII_DEBUG = false)
当 YII_DEBUG === true 时,HttpCache 会强制跳过所有缓存逻辑,包括 ETag 校验和 304 返回。开发阶段测试 ETag 前,务必确认 index.php 中已设为 defined('YII_DEBUG') or define('YII_DEBUG', false);。
避免干扰响应体内容
ETag 是对整个响应体做哈希计算(除非你显式配了 etagSeed)。如果视图里混入了用户态信息(如当前用户名、随机数、未缓存的实时时间),会导致 ETag 总是变化。建议:
- 把动态内容抽离到 AJAX 加载
- 确保
etagSeed回调所依赖的数据,在 action 执行早期就确定且稳定 - 不要在视图中用
date('Y-m-d H:i:s')输出时间,改用 JS 渲染或服务端统一注入
配置示例(放在控制器的 behaviors() 方法中):
public function behaviors()
{
return [
[
'class' => 'yii\filters\HttpCache',
'only' => ['view'],
'etagSeed' => function ($action, $params) {
$id = (int) $params['id'] ?? 0;
if ($id) {
$post = \app\models\Post::findOne($id);
return $post ? $post->updated_at . '|' . $post->status : 'not-found';
}
return 'invalid-id';
},
],
];
}
这样配置后,首次请求返回 200 并带 ETag: "xxx" 头;后续相同 URL 请求若携带 If-None-Match: "xxx",Yii 就会跳过视图渲染,直接返回 304 状态码。


















