yii2 response屢次輸出問題的查找

{
    "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/*"
                                                                                                                                            ]
                                                                                                                                        }
                                                                                                                                    }
                                                                                                                                }
                                                                                                                            }
                                                                                                                        }
                                                                                                                    }
                                                                                                                }
                                                                                                            }
                                                                                                        }
                                                                                                    }
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
View Code

以上是現象。php

action:web

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

訪問這個action產生的。由於我這個controller繼承了同事寫的一個基controller,代碼以下:api

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);app

發現該事件Response::EVENT_BEFORE_SEND被屢次觸發,這就致使了上面那個現象。yii

在基礎controller中沒有檢測該事件是否綁定handler,形成了屢次屢次重複綁定,由於在該次執行中對多個controller進行了實例化。ide

init中改成:ui

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']);
        }
    }

  方法this

不過在加入了該判斷後,發現少了一些輸出,不過還有六次輸出,以下:spa

{
    "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/*",
                            ]
                        }
                    }
                }
            }
        }
    }
}

忽然發現前面輸出的是:code

"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實例化,這種狀況通常是不常見的。因此出現這種現象是特定狀況。問題已找到。

相關文章
相關標籤/搜索