drodata
你代码中的配置仅对正常的网页请求,ajax 请求的个性化错误信息可通过配置
response
组件实现。你遇到的 500 错误是因为 response 组件在遇到错误时,直接把错误传递到客户端并被 jQuery 捕获。可以借助 Response 的 beforeSend 事件改变这种默认的行为:在发送错误前将错误信息进行封装,
'components' => [ 'response' => [ 'class' => 'yii\web\Response', 'on beforeSend' => function ($event) { $response = $event->sender; // 这里我们仅针对 ajax 请求 if ($response->format == \yii\web\Response::FORMAT_JSON) { if ($response->data !== null) { // 手动将抛出异常的状态码改为 200, 确保不被 jQuery 捕获 $response->statusCode = 200; // 自定义错误显示格式,把真正的响应数据存储在 'data' option 内 $response->data = [ 'success' => $response->isSuccessful, 'data' => $response->data, ]; } } }, ], ],
配置后,如果通过 ajax 访问下面的 action,
// in TestController.php public function actionAjaxRead() { Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; // 这里将抛出异常 return 3/0; }
$.post("/test/ajax-read", function(response) { console.log(response) })
响应内容将输出:
参考: https://www.yiiframework.com/doc/guide/2.0/zh-cn/runtime-handling-errors#error-format
@小叮当的肚兜 errorHandler 组件接管异常处理时,能捕获绝大部分异常,遇到不能识别的异常,才会调用 convertExceptionToArray() 处理。 https://github.com/yiisoft/yii2/blob/master/framework/web/ErrorHandler.php#L107-L132
"An internal server error occurred" 就是在这个方法内产生的 (https://github.com/yiisoft/yii2/blob/master/framework/web/ErrorHandler.php#L146)
你说的故意配错数据导致 500 错误出现我没能重现出来。如果故意把数据库密码输入错误,errorHandler 会捕获 yii\db\Exception:
这个异常是通过
site/error
通过 error 视图显示出来的- drodata 回答了问题 自定义错误页面和 json 响应格式
你代码中的配置仅对正常的网页请求,ajax 请求的个性化错误信息可通过配置
response
组件实现。你遇到的 500 错误是因为 response 组件在遇到错误时,直接把错误传递到客户端并被 jQuery 捕获。可以借助 Response 的 beforeSend 事件改变这种默认的行为:在发送错误前将错误信息进行封装,
'components' => [ 'response' => [ 'class' => 'yii\web\Response', 'on beforeSend' => function ($event) { $response = $event->sender; // 这里我们仅针对 ajax 请求 if ($response->format == \yii\web\Response::FORMAT_JSON) { if ($response->data !== null) { // 手动将抛出异常的状态码改为 200, 确保不被 jQuery 捕获 $response->statusCode = 200; // 自定义错误显示格式,把真正的响应数据存储在 'data' option 内 $response->data = [ 'success' => $response->isSuccessful, 'data' => $response->data, ]; } } }, ], ],
配置后,如果通过 ajax 访问下面的 action,
// in TestController.php public function actionAjaxRead() { Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; // 这里将抛出异常 return 3/0; }
$.post("/test/ajax-read", function(response) { console.log(response) })
响应内容将输出:
参考: https://www.yiiframework.com/doc/guide/2.0/zh-cn/runtime-handling-errors#error-format
- drodata 发表了说说Yii 官网论坛升级完毕,围观"StackOverflow 范儿" 的新论坛……
rules()
内声明规则的格式是:[ ['attribute1', 'attribute2', ...], // 注意这里必须是字符串,不能是数组 'validator', 'on' => ['scenario1', 'scenario2', ...], 'property1' => 'value1', 'property2' => 'value2', ... ]
你检查一下自己 Goods 模型内的规则是不是按照上面的要求。拿下面这个 required 规则来说:
public function rules() { [['container_id'], 'required'], }
如果你写成:
[['container_id'], ['required']],
就会重现你遇到的错误。
从第一张截图中的堆栈信息来看,应该不是 Html 创建下拉菜单的问题,更像是表单提交时哪个模型的验证规则出了问题,注意
Validator::createValidator()
处。就这么说吧,就是创建下拉菜单的时候报的错 去掉创建那一行就没问题 ,真的不知道为什么~~
去掉生成下拉菜单部分代码后没问题是因为去掉后你的表单除了提交按钮外什么也没有了,自然不会出错。
在服务器终端输入
./yii
, 输出内容大致如下:This is Yii version 2.0.13.1. The following commands are available: - asset Allows you to combine and compress your JavaScript and CSS files. asset/compress (default) Combines and compresses the asset files according to the given configuration. asset/template Creates template of configuration file for [[actionCompress]]. - billing billing/create 每月月初生成上月电子账单 billing/flush 清除上月账单信息
里面列出了所有可用的 actions (上面的
billing
是我自定义的一个控制器), 确认一下里面有你要执行的 action.registerJs() 和 registerJsFile() 内都有放置位置的选项,若 js file 以 asset 形式存在,通过调整 depends 依赖关系的顺序来改变加载的顺序。
但是存在一个问题是accessChecker的配置只能通过字符串类名初始化一个默认的组件。
...
不过很遗憾这个办法只能支持引用应用的组件而不能引用自己模块的组件。
yii\web\User::accessChecker 的类型是 yii\rbac\CheckAccessInterface, 如果你想通过配置 accessChecker 的办法实现,直接将其值设置成 admin 模块的 authManager 即可:
'user' => [ 'accessChecker' => Yii::$app->admin->authManager, ],
按照你上面的配置,应用内会出现两个 authManager 实例:一个在应用内,通过
Yii::$app->authManager
可访问;另一个在 admin 模块内,通过Yii::$app->admin->authManager
可访问。通常用来判断权限的Yii::$app->user->can()
方法使用的是第一个 authManager.若想在 admin 模块内指定使用 admin 模块内的 authManager, 需要在模块内的 init() 内将应用内的 authManager 替换掉,例如:
// in admin Module public function init() { parent::init(); \Yii::$app->set('authManager', $this->get('authManager')); }
error handler 不工作的原因和 authManager 类似,但稍微有些不同,具体可参考: https://www.yiiframework.com/forum/index.php/topic/74234-how-to-load-an-errorhandler-in-a-module/
- drodata 赞了回答
ip2long和long2ip满足你的需求