如何在 Laravel 5.4 中生成 API 错误响应?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43245853/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to produce API error responses in Laravel 5.4?
提问by Alex
Whenever I make a call to /api/v1/posts/1
, the call is forwarded to the show
method
每当我调用 时/api/v1/posts/1
,调用都会转发到该show
方法
public function show(Post $post) {
return $post;
}
in PostController.php
resourceful controller. If the post does exist, the server returns a JSON response. However, if the post does notexist, the server returns plain HTML, despite the request clearly expecting JSON in return. Here's a demonstration with Postman.
在PostController.php
足智多谋的控制器中。如果帖子确实存在,服务器将返回一个 JSON 响应。但是,如果后期不不存在,服务器返回纯HTML,尽管要求显然有所回报JSON。这是 Postman 的演示。
The problem is that an API is supposed to return application/json
, not text/html
. So, here are my questions:
问题是 API 应该返回application/json
,而不是text/html
。所以,这里是我的问题:
1.Does Laravel have built-in support for automaticallyreturning JSON if exceptions occur when we use implicit route model binding (like in show
method above, when we have 404)?
1.当我们使用隐式路由模型绑定时(如上面的方法,当我们有 404 时),如果发生异常,Laravel 是否有内置支持自动返回 JSON show
?
2.If it does, how do I enable it? (by default, I get plain HTML, not JSON)
2.如果是,我该如何启用它?(默认情况下,我得到纯 HTML,而不是 JSON)
If it doesn't what's the alternative to replicating the following across every singleAPI controller
如果不是,在每个API 控制器中复制以下内容的替代方法是什么
public function show($id) {
$post = Post::find($id); // findOrFail() won't return JSON, only plain HTML
if (!$post)
return response()->json([ ... ], 404);
return $post;
}
3.Is there a generic approach to use in app\Exceptions\Handler
?
3.有没有通用的方法可以使用app\Exceptions\Handler
?
4.What does a standard error/exception response contain? I googled this but found many custom variations.
4.标准错误/异常响应包含什么?我用谷歌搜索了这个,但发现了许多自定义变体。
5.And why isn't JSON response still built into implicit route model binding? Why not simplify devs life and handle this lower-level fuss automatically?
5.为什么 JSON 响应仍然没有内置到隐式路由模型绑定中?为什么不简化开发人员的生活并自动处理这种较低级别的大惊小怪?
EDIT
编辑
I am left with a conundrum after the folks at Laravel IRC advised me to leave the error responses alone, arguing that standard HTTP exceptions are rendered as HTML by default, and the system that consumes the API should handle 404s without looking at the body. I hope more people will join the discussion, and I wonder how you guys will respond.
在 Laravel IRC 的人建议我不要管错误响应后,我遇到了一个难题,他们认为标准 HTTP 异常默认呈现为 HTML,并且使用 API 的系统应该处理 404 而不查看正文。我希望更多的人加入讨论,不知道你们会如何回应。
回答by Juliano Petronetto
I use this code in app/Exceptions/Handler.php
, probably you will need making some changes
我在 中使用此代码app/Exceptions/Handler.php
,可能您需要进行一些更改
public function render($request, Exception $exception)
{
$exception = $this->prepareException($exception);
if ($exception instanceof \Illuminate\Http\Exception\HttpResponseException) {
return $exception->getResponse();
}
if ($exception instanceof \Illuminate\Auth\AuthenticationException) {
return $this->unauthenticated($request, $exception);
}
if ($exception instanceof \Illuminate\Validation\ValidationException) {
return $this->convertValidationExceptionToResponse($exception, $request);
}
$response = [];
$statusCode = 500;
if (method_exists($exception, 'getStatusCode')) {
$statusCode = $exception->getStatusCode();
}
switch ($statusCode) {
case 404:
$response['error'] = 'Not Found';
break;
case 403:
$response['error'] = 'Forbidden';
break;
default:
$response['error'] = $exception->getMessage();
break;
}
if (config('app.debug')) {
$response['trace'] = $exception->getTrace();
$response['code'] = $exception->getCode();
}
return response()->json($response, $statusCode);
}
Additionally, if you will use formRequest validations, you need override the method response
, or you will be redirected and it may cause some errors.
此外,如果您将使用 formRequest 验证,则需要覆盖该方法response
,否则您将被重定向并可能导致一些错误。
use Illuminate\Http\JsonResponse;
...
public function response(array $errors)
{
// This will always return JSON object error messages
return new JsonResponse($errors, 422);
}
回答by Jared Rolt
- Is there a generic approach to use in app\Exceptions\Handler?
- 是否有在 app\Exceptions\Handler 中使用的通用方法?
You can check if json is expected in the generic exception handler.
您可以检查通用异常处理程序中是否需要 json。
// app/Exceptions/Handler.php
public function render($request, Exception $exception) {
if ($request->expectsJson()) {
return response()->json(["message" => $exception->getMessage()]);
}
return parent::render($request, $exception);
}
回答by Sayantan Das
The way we have handled it by creating a base controller which takes care of the returning response part. Looks something like this,
我们通过创建一个负责返回响应部分的基本控制器来处理它。看起来像这样,
class BaseApiController extends Controller
{
private $responseStatus = [
'status' => [
'isSuccess' => true,
'statusCode' => 200,
'message' => '',
]
];
// Setter method for the response status
public function setResponseStatus(bool $isSuccess = true, int $statusCode = 200, string $message = '')
{
$this->responseStatus['status']['isSuccess'] = $isSuccess;
$this->responseStatus['status']['statusCode'] = $statusCode;
$this->responseStatus['status']['message'] = $message;
}
// Returns the response with only status key
public function sendResponseStatus($isSuccess = true, $statusCode = 200, $message = '')
{
$this->responseStatus['status']['isSuccess'] = $isSuccess;
$this->responseStatus['status']['statusCode'] = $statusCode;
$this->responseStatus['status']['message'] = $message;
$json = $this->responseStatus;
return response()->json($json, $this->responseStatus['status']['statusCode']);
}
// If you have additional data to send in the response
public function sendResponseData($data)
{
$tdata = $this->dataTransformer($data);
if(!empty($this->meta)) $tdata['meta'] = $this->meta;
$json = [
'status' => $this->responseStatus['status'],
'data' => $tdata,
];
return response()->json($json, $this->responseStatus['status']['statusCode']);
}
}
Now you need to extend this in your controller
现在你需要在你的控制器中扩展它
class PostController extends BaseApiController {
public function show($id) {
$post = \App\Post::find($id);
if(!$post) {
return $this->sendResponseStatus(false, 404, 'Post not found');
}
$this->setResponseStatus(true, 200, 'Your post');
return $this->sendResponseData(['post' => $post]);
}
}
You would get response like this
你会得到这样的回应
{
"status": {
"isSuccess": false,
"statusCode": 404,
"message": "Post not found"
}
}
{
"status": {
"isSuccess": true,
"statusCode": 200,
"message": "Your post"
},
"data": {
"post": {
//Your post data
}
}
}
回答by francis ngangue
You just use use Illuminate\Support\Facades\Response;
.
then, make the return as am:
您只需使用use Illuminate\Support\Facades\Response;
. 然后,按 am 返回:
public function index(){
$analysis = Analysis::all();
if(empty($analysis)) return Response::json(['error'=>'Empty data'], 200);
return Response::json($analysis, 200, [], JSON_NUMERIC_CHECK);
}
And now you will have a JSON return....
现在你将有一个 JSON 返回......