必须先启用YII_DEBUG=true并强制显示错误,再查Web服务器日志、open_basedir限制、errorHandler配置位置及CSRF验证,逐项排除环境与框架层拦截问题。

Yii2服务器500报错默认不显示真实错误,只返回空白页或通用500响应——这不是代码写错了,而是PHP错误被静默吞掉、Web服务器拦截、或框架未进入异常处理流程。必须先让错误浮出来,才能定位问题。
强制在index.php中打开PHP错误显示
生产环境的display_errors通常被禁用,导致500时看不到任何线索。最直接有效的做法是在web/index.php顶部立即启用:
- 确认第一行是:
defined('YII_DEBUG') or define('YII_DEBUG', true); - 确保同文件中
defined('YII_ENV') or define('YII_ENV', 'dev'); - 在这两行下方**立刻追加**:
error_reporting(E_ALL); ini_set('display_errors', '1'); - 如果仍无输出,检查
php.ini中display_errors = On是否生效(尤其Nginx+PHP-FPM组合下,FPM pool配置可能覆盖它)
检查Web服务器是否提前拦截了错误
Nginx或Apache可能在PHP执行前就返回500,比如open_basedir限制、权限拒绝、或FastCGI通信失败。这类错误根本不会进Yii流程,所以errorHandler配置无效。
- Nginx:查看
error_log,重点搜open_basedir、Permission denied、recv() failed - Apache:查
logs/error.log,注意mod_php崩溃或SELinux拒绝日志 - IIS:在管理器中启用“详细错误”,并确认
web.config没屏蔽PHP错误输出 - 常见陷阱:
open_basedir路径没包含vendor/或runtime/目录,realpath()调用直接失败
验证errorHandler是否真正接管了异常
即使开了调试,如果config/web.php里errorHandler配置位置不对或缺失,异常仍会回落到PHP默认错误页。
-
errorHandler组件必须放在urlManager之前,否则errorAction路由无法解析 - 确保配置项为:
'errorAction' => 'site/error',且SiteController中已注册该action(不是手写actionError()) - 检查
views/site/error.php是否存在且可读;若该视图本身有语法错误,会导致二次500,最终显示空白 - 临时在
error.php开头加<?php var_dump($exception ?? 'no exception'); die; ?>,确认变量是否传入
POST请求500大概率是CSRF验证失败
AJAX POST、表单提交、或第三方回调(如微信通知)触发500,90%以上是因为enableCsrfValidation为true但没传token。
- 现象:
curl -X POST http://yoursite.com/api/webhook直接500,浏览器F12 Network里看Response为空 - 快速验证:在对应Controller里加
public $enableCsrfValidation = false;,再试一次 - 安全做法:API接口应全局关闭CSRF(
'request' => ['enableCsrfValidation' => false]),前端表单则必须带<input name="_csrf" value="<?= Yii::$app->request->csrfToken ?>"> - 注意:
beforeAction()里动态关CSRF时,要确保parent::beforeAction($action)在最后调用,否则无效
真正难排查的500往往卡在「连错误都打不出来」的环节:Web服务器权限、PHP扩展缺失、open_basedir路径断裂、或runtime目录不可写。别急着改业务代码,先让错误出现在屏幕上——这是所有后续动作的前提。


















