2016-08-05 33 views
5

Zdefiniowałem niestandardową klasę odpowiedzi i próbowałem użyć jej w module.Moduł niestandardowej odpowiedzi Yii2 klasy

W akcji kontrolera zwracam tablicę wyników, ale niestandardowa klasa odpowiedzi nie jest używana.

Zamiast klasa używany jest domyślny Yii \ web \ Response

Moja implementacja

Konfiguracja modułu w config/web.php:

'mymodule' => [ 
     'class' => 'app\modules\mymod\Mymod', 
     'components' => [     
      'response' => [ 
       'class' => 'app\modules\mymod\components\apiResponse\ApiResponse', 
       'format' => yii\web\Response::FORMAT_JSON, 
       'charset' => 'UTF-8', 
      ], 
     ], 
    ], 

W regulatorze i zmodyfikowano metodę zachowań:

public function behaviors() { 
    $behaviors = parent::behaviors();   
    $behaviors['contentNegotiator'] = [ 
     'class' => 'yii\filters\ContentNegotiator',    
     'response' => $this->module->get('response'),     
     'formats' => [ //supported formats 
      'application/json' => \yii\web\Response::FORMAT_JSON, 
     ], 
    ]; 
    return $behaviors; 
} 

W akcji czy zrobić:

public function actionIndex() { 

    \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 

    $dataList = [ 
     ['id' => 1, 'name' => 'John', 'surname' => 'Davis'], 
     ['id' => 2, 'name' => 'Marie', 'surname' => 'Baker'], 
     ['id' => 3, 'name' => 'Albert', 'surname' => 'Bale'], 
    ]; 
    return $dataList; 
} 

uzyskać ten wynik (jak oczekiwano od Yii \ web \ Response):

[ 
{ 
    "id": 1, 
    "name": "John", 
    "surname": "Davis" 
}, 
{ 
    "id": 2, 
    "name": "Marie", 
    "surname": "Baker" 
}, 
{ 
    "id": 3, 
    "name": "Albert", 
    "surname": "Bale" 
} 
] 

Ale jeśli mogę zmienić działanie to:

$dataList = [ 
    ['id' => 1, 'name' => 'John', 'surname' => 'Davis'], 
    ['id' => 2, 'name' => 'Marie', 'surname' => 'Baker'], 
    ['id' => 3, 'name' => 'Albert', 'surname' => 'Bale'], 
]; 
//return $dataList; 

$resp = $this->module->get('response'); //getting the response component from the module configuration 
$resp->data = $dataList; 

return $resp; 

następnie uzyskać oczekiwany wynik, który brzmi następująco:

{ 
"status": { 
    "response_code": 0, 
    "response_message": "OK", 
    "response_extra": null 
}, 
"data": [ 
    { 
     "id": 1, 
     "name": "John", 
     "surname": "Davis" 
    }, 
    { 
     "id": 2, 
     "name": "Marie", 
     "surname": "Baker" 
    }, 
    { 
     "id": 3, 
     "name": "Albert", 
     "surname": "Bale" 
    } 
]} 

Wygląda na to, że określone przeze mnie zachowania nic nie robią.

Co należy zrobić, aby po prostu zwrócić tablicę w działaniu i używany jest niestandardowy komponent odpowiedzi?

góry dzięki

Odpowiedz

3

yii\base\Module nie posiada składnik reakcji, więc konfiguracja nie będzie działać. Zamiast dodawać komponent response do swojego modułu, możesz zmienić Yii::$app->response w funkcji MyMod::init().

Jeśli chcesz całkowicie zastąpić Yii::$app->response przez własnego komponentu:

public function init() 
{ 
    parent::init(); 

    \Yii::configure(\Yii::$app, [ 
     'components' => [ 
      'response' => [ 
       'class' => 'app\modules\mymod\components\apiResponse\ApiResponse', 
       'format' => yii\web\Response::FORMAT_JSON, 
       'charset' => 'UTF-8', 
      ], 
     ] 
    ]); 
} 

ale myślę, że to jest zły pomysł, aby całkowicie zastąpić składnik odpowiedź aplikacji nadrzędnej w module. Lepszym sposobem jest modyfikować zachowanie reakcji dla Twoich potrzeb. Na przykład można użyć EVENT_BEFORE_SEND i budować własną strukturę danych w odpowiedzi:

public function init() 
{ 
    parent::init(); 

    // you can use ContentNegotiator at the level of module 
    // and remove this behavior declaration from controllers 
    \Yii::configure($this, [ 
     'as contentNegotiator' => [ 
      'class' => 'yii\filters\ContentNegotiator', 
      // if in a module, use the following IDs for user actions 
      // 'only' => ['user/view', 'user/index'] 
      'formats' => [ 
       'application/json' => Response::FORMAT_JSON, 
      ], 
     ], 
    ]); 


    // you can daclare handler as function in you module and pass it as parameter here 
    \Yii::$app->response->on(Response::EVENT_BEFORE_SEND, function ($event) { 
     $response = $event->sender; 
     // here you can get and modify everything in current response 
     // (data, headers, http status etc.) 
     $response->data = [ 
      'status' => 'Okay', 
      'data' => $response->data 
     ]; 
    }); 
} 
+0

Tak, ja nie chce zastąpić składnik reakcji aplikacji za pośrednictwem modułu. Wystarczy użyć niestandardowego komponentu odpowiedzi w module. Dziękujemy! – Jepi

+0

@Jepi następnie użyj pierwszej opcji. Jeśli zastąpisz komponent odpowiedzi aplikacji funkcją 'init' modułu, wpłynie to tylko na twój moduł. Aby zastąpić jakiś komponent w całej aplikacji (należy uwzględnić inne komponenty), należy dokonać wymiany w ładowaniu początkowym – oakymax

+0

@Jepi Miałem na myśli, że aplikacja nadrzędna może już mieć swoją implementację komponentu odpowiedzi.Na przykład można zainicjować niektóre usługi rejestrowania lub debugowania, które są wspólne dla wszystkich modułów. Zastępując komponent w module, całkowicie blokujesz możliwość dostosowania tego komponentu do modułu w aplikacji nadrzędnej. Więc jeśli spodziewasz się, że twój moduł będzie używany w innych aplikacjach, miej to na uwadze. – oakymax