生产环境必须关闭错误显示并仅记录日志:php.ini中display_errors设为off,yii_debug=false且禁用debug模块,正确配置errorhandler(置于urlmanager前)和log组件,同时nginx/apache需启用错误拦截。

生产环境必须关掉所有错误显示,只记录日志;否则任何 PHP 错误(包括 Notice)都会直接暴露路径、SQL 片段、变量值,等于给攻击者递钥匙。
php.ini 里 display_errors 必须设为 Off
这是第一道防线,不能靠代码里 ini_set('display_errors', '0') 补救——像解析错误(Parse error)这类致命问题,在脚本执行前就发生了,ini_set 根本没机会运行。
- 确认生效方式:在服务器上执行
php -i | grep display_errors,或建个phpinfo()页面看输出 - 注意多配置文件场景:如果用 php-fpm,除了全局
php.ini,还要检查 pool 级的www.conf,加一行php_admin_flag[display_errors] = off才能彻底锁死 - 别信“开发机改了就行”:线上环境很可能走的是另一套配置,必须逐台验证
YII_DEBUG 和 debug 模块必须双关
YII_DEBUG = true 不仅让框架显示堆栈,还会默认启用 yii\debug\Module —— 这玩意儿在生产环境极其危险:它把 SQL 原语、文件绝对路径、类名调用链全塞进调试工具栏,而且 AJAX 接口 /debug/default/toolbar?tag=xxx 几乎不校验权限,IP 白名单极易被伪造绕过。
- 入口文件
web/index.php顶部两行必须是:defined('YII_DEBUG') or define('YII_DEBUG', false);和defined('YII_ENV') or define('YII_ENV', 'prod'); - 配置文件
config/web.php中,确保没有'debug' => [...]这样的模块注册;哪怕留着,也要删掉'bootstrap' => ['debug'] - 别图省事用
'allowedIPs' => ['127.0.0.1']来“保底”,反向代理头(如 X-Forwarded-For)配置错就会失效
errorHandler 配置要到位,否则白屏或 500
关掉显示后,错误不能丢,得跳转到友好页面并写入日志。Yii2 的 errorHandler 组件就是干这个的,但它必须放在 urlManager 之前,否则路由解析失败,errorAction 直接失效。
- 在
config/web.php的'components'数组中,确保有:'errorHandler' => ['errorAction' => 'site/error'] -
SiteController里不要手写actionError(),而是用现成的:'error' => ['class' => 'yii\web\ErrorAction'] - 视图文件必须严格命名:
@views/site/error.php、error-404.php、error-500.php,大小写和连字符一个都不能错 - 视图中禁止输出
$exception->getTraceAsString()或$exception->getFile(),这些在生产环境会泄露敏感路径
log 组件要指定 error_log 路径且确保可写
错误不显示,但得可查。Yii2 默认把日志写进 runtime/logs,但如果 Web 服务器进程没权限写入,或者磁盘满了,日志就丢了——你既看不到错误,也收不到告警。
- 在
config/web.php的'log'配置里,至少保留一个FileTarget,明确指定'logFile' => '@runtime/logs/app.log' - 手动检查目录权限:
ls -ld runtime/logs,确保属主是 Web 服务用户(如www-data),且有写权限 - 避免用空
error_log值:PHP 会退化到 SAPI 日志(比如 Apache 的error_log),位置分散难定位 - 日志等级建议设为
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT,开太多E_NOTICE会让日志爆炸,反而掩盖真正的问题
最常被忽略的一点:Nginx/Apache 层也要拦截原始错误响应。比如 Nginx 的 fastcgi_intercept_errors on; 必须开启,否则 PHP 返回 500 时,Web 服务器可能直接透传原始错误页,绕过 Yii 的 errorHandler。这层漏掉,前面所有配置都白搭。











