【问题标题】:Yii2 module custom response classYii2 模块自定义响应类
【发布时间】:2016-08-05 16:30:09
【问题描述】:

我已经定义了一个自定义响应类,并试图在模块中使用它。

在控制器操作中,我返回一个结果数组,但未使用自定义响应类。

相反,使用的类是默认的 yii\web\Response

我的实现

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',
            ],
        ],
    ],

在控制器中我编辑了行为方法:

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;
}

如果我这样做,在行动中:

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;
}

我得到了这个结果(正如 yii\web\Response 所期望的那样):

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

但如果我将操作更改为:

$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;

然后我得到预期的结果,就是这样:

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

我定义的行为似乎没有做任何事情。

我需要做什么才能在操作中返回数组并使用自定义响应组件?

提前致谢

【问题讨论】:

    标签: php yii2


    【解决方案1】:

    yii\base\Module 没有响应组件,因此您的配置将不起作用。 而不是将response 组件添加到您的模块中,您应该在MyMod::init() 函数中更改Yii::$app->response

    如果你想用你自己的组件完全替换Yii::$app->response

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

    但我认为在模块中完全替换父应用程序的响应组件是一个坏主意。更好的方法是根据您的需要修改响应行为。例如,您可以使用EVENT_BEFORE_SEND 并构建自己的数据结构作为响应:

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

    【讨论】:

    • 是的,我不想通过模块替换应用程序响应组件。只是为了使用模块中的自定义响应组件。谢谢!
    • @Jepi 然后使用第一个选项。如果您将应用程序响应组件替换为模块的init 函数,那么它将仅影响您的模块。要替换整个应用程序中的某些组件(包括其他组件),应在引导过程中进行替换
    • @Jepi 我的意思是父应用程序可能已经实现了响应组件。例如,可以启动一些对所有模块都通用的日志记录或调试服务。通过替换模块中的组件,您完全阻止了在父应用程序中为您的模块自定义此组件的能力。因此,如果您希望您的模块将在其他应用程序中使用,请记住这一点
    • 我牢记这一点。所以我将使用第二个选项,并更改 yii\web\Response 的 data 属性以匹配自定义结果。
    • 关于使用第一个选项,但仍然可以在父应用程序中自定义组件。 1. 如果我在 config/web.php 中定义了一个响应组件 2. 在模块 init() 中我可以得到 $components_arr = this->getComponents(); 3. 检查是否配置了响应组件 array_key_exists('response', $components_arr) 4. 如果存在,配置应用程序。 \Yii::configure(\Yii::$app, [ 'components' => [ 'response' => $this->response, ] ]); 5. 否则,什么都不做。使用应用程序组件。没事吧?
    猜你喜欢
    • 1970-01-01
    • 2015-02-13
    • 2015-02-08
    • 2015-08-04
    • 2021-11-29
    • 1970-01-01
    • 2018-09-12
    • 2015-03-06
    • 1970-01-01
    相关资源
    最近更新 更多