yii2.0.47启用全页缓存需正确配置yii\filters\pagecache:在控制器behaviors()中声明,设置only、duration及dependency(文件/数据库/表达式),规避csrf、用户态混存、response头干扰等陷阱,并通过缓存键、响应头x-page-cache和手动查缓存验证效果。

Yii2.0.47 启用页面全页缓存,核心是用好 yii\filters\PageCache 过滤器,它能跳过控制器动作执行、视图渲染全过程,直接返回已缓存的 HTML 响应。这不是“加个配置就行”的事,关键在行为定义位置、缓存生命周期控制和依赖联动是否到位。
一、在控制器中正确声明 PageCache 行为
必须在控制器类中重写 behaviors() 方法,不能只在 action 内部临时调用。PageCache 是动作级过滤器,需在请求进入前就注册生效:
- 确保
class指向'yii\filters\PageCache'(注意不是yii\caching\*下的类) -
only参数限定作用范围,例如['index', 'about'],避免误缓存登录页或表单页 -
duration设为整数秒,如3600表示 1 小时;设为0则禁用过期,仅靠依赖触发刷新 - 若需动态控制,可用回调函数:
'duration' => function () { return Yii::$app->user->isGuest ? 600 : 3600; }
二、配合缓存依赖实现智能刷新
单纯靠时间过期容易导致内容陈旧,推荐绑定数据变更信号。PageCache 支持 dependency 配置,常见组合有:
-
文件依赖:监控模板或配置文件变化,适合静态内容页
'class' => 'yii\caching\FileDependency', 'fileName' => '@app/views/site/index.php' -
数据库依赖:当某张表记录更新时自动失效缓存
'class' => 'yii\caching\DbDependency', 'sql' => 'SELECT MAX(updated_at) FROM post WHERE status = 1' -
表达式依赖:基于运行时逻辑判断,比如检查某个开关是否开启
'class' => 'yii\caching\ExpressionDependency', 'expression' => '!Yii::$app->params['maintenance_mode']'
注意:所有依赖类都必须能被正常实例化,且 SQL 查询需有明确返回值(如标量),否则缓存会始终视为“已失效”而拒绝命中。
三、规避常见陷阱
页面缓存看似简单,但几个细节不处理就会“缓存了不该缓存的”或“根本不生效”:
-
CSRF 和用户态内容冲突:含表单的页面默认带 CSRF token,不能直接全页缓存。要么移除表单,要么对 token 字段使用
FragmentCache单独绕过 -
未登录用户与登录用户混缓存:同一 URL 对不同身份用户返回不同内容,必须启用
variations区分,例如:'variations' => [Yii::$app->user->id ?? 0] -
Response 头干扰:如果控制器中手动设置了
Cache-Control: no-cache或Expires,会覆盖 PageCache 的 header,需清理或统一管理 -
调试模式干扰:开发环境开启
YII_DEBUG时,PageCache 默认被跳过。上线前务必确认YII_DEBUG = false且应用配置加载的是生产版
四、验证与调试方法
别只看页面是否变快,要确认缓存真正写入并复用:
- 访问目标页面后,检查 Redis 或文件缓存目录,确认生成了类似
pagecache_5a8b2c...的键(取决于keyPrefix设置) - 在浏览器开发者工具 Network 面板中,观察响应头是否含
X-Page-Cache: HIT(需在 PageCache 配置中加'headers' => ['X-Page-Cache' => 'HIT']) - 修改依赖文件(如模板)后刷新,确认响应头变为
X-Page-Cache: MISS并重新生成缓存 - 用
Yii::$app->cache->get($key)手动查缓存内容,验证 HTML 片段是否完整、无 PHP 错误残留
页面缓存不是万能开关,但它在内容稳定、访问量大的场景下效果立竿见影。只要依赖设得准、变量分得清、环境配得稳,一次配置就能长期省下大量 CPU 和 DB 压力。











