如何更改 JSON 请求 Cakephp 3 的错误响应结构
How to change error response structure for JSON request Cakephp 3
在我的 router.php 中,我启用了 json 扩展和这样的路由文件扩展
Router::prefix('api', function (RouteBuilder $routes) {
$routes->extensions(['json']);
$routes->fallbacks('DashedRoute');
});
一切正常。当我想给出错误消息时,我使用这个 JSON 结构
{
"data": {
"error": "Please provide username"
}
}
当我抛出 ForbiddenException 时,我得到了这样的结构
{
"message": "Forbidden",
"url": "/sfworxerp/api/v1/attendances/getEmployeesAttendance.json",
"code": 403
}
但我需要这种格式。
{
"data": {
"error": "Forbidden",
"code": 403
}
}
到目前为止我已经做了
我创建了一个像这样的自定义 ExceptionRenderer
命名空间App\Error;
use Cake\Error\ExceptionRenderer;
class AppExceptionRenderer extends ExceptionRenderer
{
public function forbidden($error)
{
return 'test';
}
}
并将其添加到我的 app.php 文件
'Error' => [
'errorLevel' => E_ALL & ~E_DEPRECATED,
'exceptionRenderer' => 'App\Error\AppExceptionRenderer',
'skipLog' => [],
'log' => true,
'trace' => true,
],
当我将字符串 'test' 的值更改为数组时,它会抛出错误
Fatal error: Call to a member function send() on a non-object in
F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Error\ErrorHandler.php
on line 186
您需要覆盖 render()
方法
use Cake\Error\ExceptionRenderer;
class AppExceptionRenderer extends ExceptionRenderer
{
public function unauthorized()
{
// do some exception specific here
}
public function render()
{
// You can output here your desired response.
// You can access exception by calling $this->exception
// For example...
$this->controller->set('response', ['foo' => 'bar']);
$this->controller->set('_serialize', 'response');
return $this->controller->response;
}
}
array
不是自定义错误方法的有效 return 类型
仔细查看文档,它说明了自定义异常渲染器方法的两个可能 return 值:
[...] Exception handling methods get the exception being handled as their argument. Your custom exception rendering can return either a string or a Response
object. Returning a Response will give you full control over the response. [...]
* 强调我的
Cookbook > Error & Exception Handling
因此,如果您想要针对特定方法的自定义响应,则必须通过 $this->controller->response
对象和 return 构建正确的响应。
修改序列化的内容和方式
但是,此类自定义方法会影响所有错误响应,而不仅仅是序列化的响应。对于侵入性较小的方法,您最好改为挂钩 _outputMessage()
,并修改视图变量和序列化配置以满足您的需要,类似于:
protected function _outputMessage($template)
{
$this->controller->set('data', [
'error' => $this->controller->viewVars['message'],
'code' => $this->controller->viewVars['code']
]);
$this->controller->set('_serialize', ['data']);
return parent::_outputMessage($template);
}
这将为每个序列化错误响应(如 JSON、XML 等)提供所需的结构,同时不影响常规错误响应。这当然只是一个非常基本的例子,但你应该明白这一点。
在我的 router.php 中,我启用了 json 扩展和这样的路由文件扩展
Router::prefix('api', function (RouteBuilder $routes) {
$routes->extensions(['json']);
$routes->fallbacks('DashedRoute');
});
一切正常。当我想给出错误消息时,我使用这个 JSON 结构
{
"data": {
"error": "Please provide username"
}
}
当我抛出 ForbiddenException 时,我得到了这样的结构
{
"message": "Forbidden",
"url": "/sfworxerp/api/v1/attendances/getEmployeesAttendance.json",
"code": 403
}
但我需要这种格式。
{
"data": {
"error": "Forbidden",
"code": 403
}
}
到目前为止我已经做了
我创建了一个像这样的自定义 ExceptionRenderer
命名空间App\Error;
use Cake\Error\ExceptionRenderer;
class AppExceptionRenderer extends ExceptionRenderer
{
public function forbidden($error)
{
return 'test';
}
}
并将其添加到我的 app.php 文件
'Error' => [
'errorLevel' => E_ALL & ~E_DEPRECATED,
'exceptionRenderer' => 'App\Error\AppExceptionRenderer',
'skipLog' => [],
'log' => true,
'trace' => true,
],
当我将字符串 'test' 的值更改为数组时,它会抛出错误
Fatal error: Call to a member function send() on a non-object in F:\public_html\sfworxerp\vendor\cakephp\cakephp\src\Error\ErrorHandler.php on line 186
您需要覆盖 render()
方法
use Cake\Error\ExceptionRenderer;
class AppExceptionRenderer extends ExceptionRenderer
{
public function unauthorized()
{
// do some exception specific here
}
public function render()
{
// You can output here your desired response.
// You can access exception by calling $this->exception
// For example...
$this->controller->set('response', ['foo' => 'bar']);
$this->controller->set('_serialize', 'response');
return $this->controller->response;
}
}
array
不是自定义错误方法的有效 return 类型
仔细查看文档,它说明了自定义异常渲染器方法的两个可能 return 值:
[...] Exception handling methods get the exception being handled as their argument. Your custom exception rendering can return either a string or a
Response
object. Returning a Response will give you full control over the response. [...]
* 强调我的
Cookbook > Error & Exception Handling
因此,如果您想要针对特定方法的自定义响应,则必须通过 $this->controller->response
对象和 return 构建正确的响应。
修改序列化的内容和方式
但是,此类自定义方法会影响所有错误响应,而不仅仅是序列化的响应。对于侵入性较小的方法,您最好改为挂钩 _outputMessage()
,并修改视图变量和序列化配置以满足您的需要,类似于:
protected function _outputMessage($template)
{
$this->controller->set('data', [
'error' => $this->controller->viewVars['message'],
'code' => $this->controller->viewVars['code']
]);
$this->controller->set('_serialize', ['data']);
return parent::_outputMessage($template);
}
这将为每个序列化错误响应(如 JSON、XML 等)提供所需的结构,同时不影响常规错误响应。这当然只是一个非常基本的例子,但你应该明白这一点。