静态页面应存数据库而非硬编码:建page表存slug、title、content等字段,用ActiveRecord封装;路由需配置urlManager规则并启用美化;控制器须判空抛404;输出前用HtmlPurifier过滤XSS。

静态页面内容硬编码在视图里,改一次要重部署?
别这么干。Yii 里所谓“静态页面”,比如关于我们、服务条款这类内容基本不变但偶尔要更新的页面,直接写死在 views/site/about.php 里,后期运营改个错别字都得找程序员发版——这不是静态,是“僵化”。真正的做法是把内容抽到数据库,视图只负责渲染。
实操建议:
- 建一张
page表,至少含slug(如'about')、title、content(TEXT 类型)、is_active - 用 Yii 的 ActiveRecord 快速封装:创建
Page模型,加findBySlug($slug)方法 - 控制器里不硬写逻辑,统一走
SiteController::actionPage($slug),查不到就抛NotFoundHttpException
路由匹配不到 /about?检查 URL 美化和规则配置
很多人写了数据库驱动的页面,但访问 /about 直接 404,不是代码问题,是路由没通。Yii 默认不自动把路径映射到 action,尤其启用了 URL 美化后更易踩坑。
实操建议:
- 确认
urlManager开启了enablePrettyUrl => true,且 Web 服务器(Nginx/Apache)已配好重写规则 - 在
config/web.php的urlManager.rules里加一条:'<slug:>' => 'site/page'</slug:> -
slug正则别写太宽,避免和已有路由冲突(比如别用.*),\w+足够覆盖about、terms这类标识符 - 清空
runtime/cache/下的路由缓存,否则改了 rules 也不生效
Page::findBySlug() 返回 null,但页面却空白不报错?
这是最隐蔽的问题:数据库查不到记录,模型返回 null,控制器若没判空直接传给视图,视图里 $model->title 就触发 PHP Notice,而 Yii 默认环境可能屏蔽了这个级别错误,结果页面白屏或标题消失,日志里还没痕迹。
实操建议:
- 控制器中必须显式检查:
$model = Page::findBySlug($slug); if (!$model || !$model->is_active) { throw new NotFoundHttpException(); } - 别依赖视图做兜底判断,视图只处理“有数据”的情况
- 开发时打开
YII_DEBUG,确保 Notice 级错误能打到日志;生产环境至少配置errorLevel包含E_NOTICE - 如果允许“临时下线”,
is_active字段比删记录更安全,也方便审计
富文本内容渲染时样式错乱或脚本执行?
content 字段存的是 HTML(比如从后台编辑器粘贴进来的),直接 = $model->content ?> 输出,既可能被 XSS 攻击,也可能因为缺少 CSS 上下文导致排版崩坏——这不是 Yii 的锅,是输出控制没做对。
实操建议:
- 永远用
= yii\helpers\HtmlPurifier::process($model->content) ?>过滤,它默认只放行安全标签(p、strong、ul等),砍掉script、style、onerror之类 - 需要保留部分样式?自定义
HtmlPurifier配置,比如允许class属性,但禁止style属性 - 别在数据库里存完整 HTML 页面结构(比如带
<html><body>),只存内容片段,由视图控制容器和布局 - 如果编辑器导出 Markdown,后端转 HTML 更可控,用
cebe/markdown扩展即可,比 HTMLPurifier 更轻量
真正麻烦的从来不是“怎么把数据库字段塞进视图”,而是内容来源是否可信、路由是否可预测、错误是否可感知——这几个点漏一个,静态页面就变成线上定时雷。









