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