如何让 Laravel 返回 JSON REST API 的自定义错误
Posted
技术标签:
【中文标题】如何让 Laravel 返回 JSON REST API 的自定义错误【英文标题】:How can I make Laravel return a custom error for a JSON REST API 【发布时间】:2014-04-20 07:21:20 【问题描述】:我正在开发某种 RESTful API。当发生一些错误时,我会抛出一个App::abort($code, $message)
错误。
问题是:我希望他抛出一个带有键“代码”和“消息”的 json 格式的数组,每个都包含上述数据。
Array
(
[code] => 401
[message] => "Invalid User"
)
有谁知道这是否可行,如果可行,我该怎么做?
【问题讨论】:
【参考方案1】:您可以将数组传递给返回的 JSON 响应:
$returnData = array(
'status' => 'error',
'message' => 'An error occurred!'
);
return Response::json($returnData, 500);
【讨论】:
谢谢!在 laravel 5 中它将是: return response()->json($returnData, 500) 如果减少 $returnData 数组的使用,也可以变得更容易【参考方案2】:转到您的app/start/global.php
。
这会将 401
和 404
的所有错误转换为自定义 json 错误,而不是 Whoops 堆栈跟踪。添加这个:
App::error(function(Exception $exception, $code)
Log::error($exception);
$message = $exception->getMessage();
// switch statements provided in case you need to add
// additional logic for specific error code.
switch ($code)
case 401:
return Response::json(array(
'code' => 401,
'message' => $message
), 401);
case 404:
$message = (!$message ? $message = 'the requested resource was not found' : $message);
return Response::json(array(
'code' => 404,
'message' => $message
), 404);
);
这是处理此错误的众多选项之一。
制作 API 最好创建自己的帮助程序,例如扩展 Response
类的 Responser::error(400, 'damn')
。
有点像:
public static function error($code = 400, $message = null)
// check if $message is object and transforms it into an array
if (is_object($message)) $message = $message->toArray();
switch ($code)
default:
$code_message = 'error_occured';
break;
$data = array(
'code' => $code,
'message' => $code_message,
'data' => $message
);
// return an error
return Response::json($data, $code);
【讨论】:
我真的很喜欢你说的第二件事。关于API,虽然我并不完全理解。我是否应该创建另一个类,在其中扩展Response
类并调用它而不是“正确的”类?就这样?
@DennisBraga 是对的。它可以帮助您在 API 中保持统一的错误响应。【参考方案3】:
这是我使用的(Laravel 5.2):
根据:https://laravel.com/docs/5.2/errors,我们可以为app\Exceptions\Handler.php
中的错误指定自定义渲染函数。我所做的只是将我的渲染函数更改为:
/**
* Render an exception into an HTTP response.
* Updated to return json for a request that wantsJson
* i.e: specifies
* Accept: application/json
* in its header
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
if ($request->ajax() || $request->wantsJson())
return response()->json(
$this->getJsonMessage($e),
$this->getExceptionHTTPStatusCode($e)
);
return parent::render($request, $e);
protected function getJsonMessage($e)
// You may add in the code, but it's duplication
return [
'status' => 'false',
'message' => $e->getMessage()
];
protected function getExceptionHTTPStatusCode($e)
// Not all Exceptions have a http status code
// We will give Error 500 if none found
return method_exists($e, 'getStatusCode') ?
$e->getStatusCode() : 500;
在此之后,您需要做的就是确保所有 API 请求都指定 Accept: application/json
标头。希望这会有所帮助:)
【讨论】:
你是国王!只需一个很小的 sn-p 我就可以处理 ajax 响应。凉爽的。示例:中止(401,'未授权');【参考方案4】:根据 Ibrahim 的回答,并非每个 ajax 请求都需要 JSON,响应“状态代码”和“状态”是不必要的,因为它们的含义相同。更重要的是,根本不需要在响应“状态”中提及,因为响应代码“说”了这一点。这样的东西应该可以完美运行:
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
if ($request->wantsJson())
return response()->json(
['message' => $e->getMessage()],
method_exists($e, 'getStatusCode') ? $e->getStatusCode() : 500);
return parent::render($request, $e);
【讨论】:
【参考方案5】:这是我在 5.6 中使用的,以便返回与内置 validate
方法相同类型的响应:
response()->json(['errors' => ['email' => ['The email is invalid.']]], 422);
【讨论】:
【参考方案6】:在 Laravel5.6 中,我通常为 app\Exceptions\Handler.php
中的错误指定自定义渲染函数。我所做的只是将我的渲染函数更改为:
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
*
* @return Response
*/
public function render($request, Exception $e)
if ($request->wantsJson() && !($e instanceof ValidationException))
$response = [
'message' => (string)$e->getMessage(),
'status_code' => 400,
];
if ($e instanceof HttpException)
$response['message'] = Response::$statusTexts[$e->getStatusCode()];
$response['status_code'] = $e->getStatusCode();
else if ($e instanceof ModelNotFoundException)
$response['message'] = Response::$statusTexts[Response::HTTP_NOT_FOUND];
$response['status_code'] = Response::HTTP_NOT_FOUND;
if ($this->isDebugMode())
$response['debug'] = [
'exception' => get_class($e),
'trace' => $e->getTrace()
];
return response()->json([
'status' => 'failed',
'status_code' => $response['status_code'],
'massage' => $response['message'],
], $response['status_code']);
return parent::render($request, $e);
【讨论】:
那个答案看起来非常好,但遗憾的是它对我不起作用,Laravel 仍然给我 ```status "error" message "An error occurred."```` 作为响应 :( 【参考方案7】:Laravel 6:
您必须在客户端的 API 请求中设置 Accept:application/json
标头,Laravel 会自动返回 JSON 格式错误。
"message": "Unauthenticated."
【讨论】:
【参考方案8】:$response['message'] ="The given data was invalid";
$error['country_id'] = ["The country field is required"];
$error['state_id'] = ["The state field is required"];
$error['name'] = ["The name field is required"];
$response['error'] = $error;
return response()->json($response,422);
【讨论】:
【参考方案9】:对于 Laravel 8
转到您的 \app\Exceptions\Handler.php
并像这样覆盖 invalidJson
方法:
// Add this line at the top of the class
use Illuminate\Validation\ValidationException;
/**
* Convert a validation exception into a JSON response.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Validation\ValidationException $exception
* @return \Illuminate\Http\JsonResponse
*/
protected function invalidJson($request, ValidationException $exception)
// You can return json response with your custom form
return response()->json([
'success' => false,
'data' => [
'code' => $exception->status,
'message' => $exception->getMessage(),
'errors' => $exception->errors()
]
], $exception->status);
响应样本:
"success": false,
"data":
"code": 422,
"message": "The given data was invalid.",
"errors":
"password": [
"The password field is required."
]
原来的方法是:
/**
* Convert a validation exception into a JSON response.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Validation\ValidationException $exception
* @return \Illuminate\Http\JsonResponse
*/
protected function invalidJson($request, ValidationException $exception)
return response()->json([
'message' => $exception->getMessage(),
'errors' => $exception->errors(),
], $exception->status);
响应样本:
"message": "The given data was invalid.",
"errors":
"password": [
"The password field is required."
]
请注意,unauthenticated
响应是在单独的方法中,因此您也可以覆盖它
/**
* Convert an authentication exception into a response.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Auth\AuthenticationException $exception
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function unauthenticated($request, AuthenticationException $exception)
return $request->expectsJson()
// Here you can change the form of the json response
? response()->json(['message' => $exception->getMessage()], 401) // <-
: redirect()->guest($exception->redirectTo() ?? route('login'));
【讨论】:
invalidJson() 在 laravel 8 的 \app\Exceptions\Handler.php 中不存在。\app\Exceptions\Handler.php
extends Illuminate\Foundation\Exceptions\Handler
, invalidJson() 存在于父类中,你只需要重写它来改变它的行为以上是关于如何让 Laravel 返回 JSON REST API 的自定义错误的主要内容,如果未能解决你的问题,请参考以下文章