{
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"error_code": 1,
"message": "OK",
"res_msg": {
"available": [
"/api/auth/view",
],
"assigned": [
"/*",
"/admin/*",
"/admin/api/*"
]
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}

以上是现象。

action:

public function actionRefresh()
{
$model = new Route();
$model->invalidate();
return $model->getRoutes();
}

访问这个action产生的。因为我这个controller继承了同事写的一个基controller,代码如下:

public function init()
{
parent::init();
//绑定beforeSend事件,更改数据输出格式
Yii::$app->getResponse()->on(Response::EVENT_BEFORE_SEND, [$this, 'beforeSend']);
} /**
* 更改数据输出格式
* 默认情况下输出Json数据
* @param \yii\base\Event $event
*/
public function beforeSend($event)
{
/* @var $response \yii\web\Response */
$response = $event->sender;
$msg = $response->statusText;
$statusCode = $response->statusCode;
$isSuccess = $response->getIsSuccessful(); if(isset($response->data['code']) && $response->data['code']==0){
$code = 0;
}else{
if($isSuccess){
$code = 1;
}else{
$code = 0;
}
}
if ($response->statusCode>=400) {
//异常处理
if (true && $exception = Yii::$app->getErrorHandler()->exception) {
$data = $response->data;
//$data = $this->convertExceptionToArray($exception);
}
//Model出错了
if ($response->statusCode==422) {
$messages=[];
foreach ($response->data as $v) {
$messages[] = $v['message'];
}
//请求错误时数据为 {"success":false,"data":{"name":"Not Found","message":"页面未找到。","code":0,"status":404}}
$data = [
'error_code' =>$code,
'message'=> implode(" ", $messages),
'res_msg'=>$response->data
];
}
$response->isSent = true;
// $response->statusCode = 200;
}
elseif ($response->statusCode>=300) {
// $response->statusCode = 200;
$data = $this->convertExceptionToArray(new ForbiddenHttpException(Yii::t('yii', 'Login Required')));
}
else{
$data = $response->data;
} //请求正确时数据
$response->data = [
'error_code' =>$code,
'message' => $msg,
'res_msg' => empty($data) ? array('message'=>'暂无数据') : $data,
]; $response->format = Response::FORMAT_JSON;
// \Yii::$app->getResponse()->getHeaders()->set('Access-Control-Allow-Origin', '*');
// \Yii::$app->getResponse()->getHeaders()->set('Access-Control-Allow-Credentials', 'true'); }

在beforeSend中Yii::info($response->statusCode);

发现该事件Response::EVENT_BEFORE_SEND被多次触发,这就导致了上面那个现象。

在基础controller中没有检测该事件是否绑定handler,造成了多次多次重复绑定,因为在该次执行中对多个controller进行了实例化。

init中改为:

public function init()
{
parent::init();
//绑定beforeSend事件,更改数据输出格式
if (!Yii::$app->response->hasEventHandlers(Response::EVENT_BEFORE_SEND)) {
// 避免重复绑定
Yii::$app->getResponse()->on(Response::EVENT_BEFORE_SEND, [$this, 'beforeSend']);
}
}

  方法

不过在加入了该判断后,发现少了一些输出,不过还有六次输出,如下:

{
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"error_code": 1,
"message": "OK",
"res_msg": {
"available": [
"/api/auth/view",
"/api/auth/create"
],
"assigned": [
"/*",
"/admin/*",
"/admin/api/*",
]
}
}
}
}
}
}
}

突然发现前面输出的是:

"IsSuccess": 1,
"ErrMsg": "OK",
"Data":{}

而这是我在另外一个基controller中绑定的事件发挥的结果格式,如下:

public function init() {
parent::init();
Event::on(
Response::className(),
Response::EVENT_BEFORE_SEND,
[$this, 'formatDataBeforeSend']
);
}

很奇怪,他为啥跟这个混在一起了?

对了,这是因为出现这种情况是在获取系统所有route的方法getAppRoutes中,而其中有对所有controller进行实例化的动作。症结就在这里了。

将init方法改造为:

public function init() {
parent::init();
if (!Event::hasHandlers(Response::className(), Response::EVENT_BEFORE_SEND)) {
Event::on(
Response::className(),
Response::EVENT_BEFORE_SEND,
[$this, 'formatDataBeforeSend']
);
}
}

不过在这样处理后,还有问题,如下:

{
"IsSuccess": 1,
"ErrMsg": "OK",
"Data": {
"error_code": 1,
"message": "OK",
"res_msg": {
"available": [
"/api/auth/view",
"/api/auth/create",
"/api/auth/update",
],
"assigned": [
"/*",
"/admin/*"
]
}
}
}

还有问题,不过这个问题的原因就在于这里因为对那个作为路由controller的中绑定事件的触发,加上正常的触发,导致了这个问题。

这个问题除了前面加上判断之外,还得处理一下,如下:

public function init() {
parent::init();
if (
!Event::hasHandlers(Response::className(), Response::EVENT_BEFORE_SEND)
&& !Yii::$app->response->hasEventHandlers(Response::EVENT_BEFORE_SEND)
) {
Event::on(
Response::className(),
Response::EVENT_BEFORE_SEND,
[$this, 'formatDataBeforeSend']
);
}
}

因为涉及到两种返回格式,且在一次访问中,多次触发controller实例化,这种情况一般是不常见的。所以出现这种现象是特定情况。问题已找到。

yii2 response多次输出问题的查找的更多相关文章

  1. response小结(一)——用response向客户端输出中文数据(乱码问题分析)

    Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象,和代表响应的response对象.request和response对象既然代表请求和响应,那我们要 ...

  2. response对象设置输出缓冲大小

    response对象设置输出缓冲大小 制作人:全心全意 通常情况下,服务器要输出到客户端的内容不会直接写到客户端,而是先写到一个输出缓冲区,在计算机术语中,缓冲区被定义为暂时放置输入或输出资料的内存. ...

  3. response的Writer输出数据的问题

    package cn.itcast.response; import java.io.IOException; import java.io.OutputStream; import java.io. ...

  4. response的outputStream输出数据的问题

    package cn.itcast.response; import java.io.IOException; import java.io.OutputStream; import java.io. ...

  5. Response.BinaryWrite()方法输出二进制图像

    protected void Page_Load(object sender, EventArgs e) { FileStream fs = new FileStream(Server.MapPath ...

  6. response常见应用、response细节、输出随机图片、定时刷新网页

      response常见应用 向客户端输出中文数据 分别以OutputStream和PrintWriter输出 多学一招:使用HTML语言里面的<meta>标签来控制浏览器行为 思考:用O ...

  7. asp.net 利用Response.Filter 获取输出内容, 变更输出内容

    重写 Response.Filter 就可以获取或更新输出到浏览器的内容       资料: https://weblog.west-wind.com/posts/2009/Nov/13/Captur ...

  8. yii2 对象跟数组输出数据到view视图方法

    public function actionJiekou(){ $url = 'http://wap.guoshihui.com/_static/wap/video/startVideo.mp4'; ...

  9. yii2 response响应配置

    response参数配置 方式一.全局配置 用于接口开发 适用:只有所有请求都是application/json类型时可用. $config = [ 'components' => [ 'res ...

随机推荐

  1. Git入门之在IDEA中使用Git上传maven项目

    下载安装git客户端: 参考博文:https://www.cnblogs.com/java-maowei/p/5950930.html 在IDEA怎么使用git上传spring的maven项目详解: ...

  2. 一百一十八:CMS系统之短信验证码加密和js代码混淆

    前面的方法存在安全隐患,只要知道发送短信验证码的接口就可以无限触发发送短信验证码 改用post请求,在前端加scrf_token验证,后面需要使用到md5加密,引入md5 from apps.form ...

  3. c语言求素数以及改进算法

    代码需要使用c99编译 #include <stdio.h> #include <stdlib.h> #include <math.h> //是否为素数 //从2到 ...

  4. babylon 初试

    出于对web端3D技术的对比,以及WebGL的发展现状和WebGPU的发展前景,我觉得有必要涉猎一下babylon.js了. 可以参考一下下列文章: 1⃣️下一代web端图形接口现状与前景:https ...

  5. docker 导出多个镜像合并成一个tar

    导出单个镜像 docker save [images] > [name.tar] 倒出多个镜像合并成一个tar包 docker save [images] [images] > [name ...

  6. jQuery 虚拟数字键盘代码

    先上效果:    js直接应用:  $('input').mynumkb(); 就出来效果 HTML: <input maxlength="4" type="tex ...

  7. C# MVC MVP

    https://www.codeproject.com/Articles/613682/Your-first-program-using-MVC-pattern-with-Csharp-W https ...

  8. 关于MySQL 5.6 中文乱码的问题(尤其是windows的gbk编码)

    一般MySQL 数据库乱码由以下几种情况造成(按照顺序): 1. 创建数据库的时候没设置编码,解决办法: 就是在创建数据库的时候设置编码, 例如: CREATE DATABASE `mydb` CHA ...

  9. Golang结构体struct的使用(结构体嵌套, 匿名结构体等)

    转自: https://studygolang.com/articles/11313 golang中是没有class的,但是有一个结构体struct,有点类似,他没有像java,c++中继承的概念,但 ...

  10. Python全栈开发之5、模块

    一.模块 1.import导入模块 #1.定义 模块:用来从逻辑上组织python代码(变量,函数,类,逻辑),本质就是.py结尾的python文件,实现一个功能 包:python package 用 ...