Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel API, how to properly handle errors

Anyone know what is the best way to handle errors in Laravel, there is any rules or something to follow ?

Currently i'm doing this :

public function store(Request $request) {   $plate = Plate::create($request->all());    if ($plate) {     return $this->response($this->plateTransformer->transform($plate));   } else {     // Error handling ?     // Error 400 bad request     $this->setStatusCode(400);     return $this->responseWithError("Store failed.");   } } 

And the setStatusCode and responseWithError come from the father of my controller :

public function setStatusCode($statusCode) {     $this->statusCode = $statusCode;      return $this; }  public function responseWithError ($message ) {     return $this->response([         'error' => [             'message' => $message,             'status_code' => $this->getStatusCode()         ]     ]);  } 

But is this a good way to handle the API errors, i see some different way to handle errors on the web, what is the best ?

Thanks.

like image 810
Spialdor Avatar asked Jun 27 '18 14:06

Spialdor


People also ask

How do you handle response in Laravel?

Note: This solution will not work for Authentication/Validation errors but most of the time these both errors are well managed by Laravel with proper human-readable response messages. You can use $response['message'] = Symfony\Component\HttpFoundation\Response::$statusTexts[$statusCode] instead of your long switch.


2 Answers

Try this, i have used it in my project (app/Exceptions/Handler.php)

public function render($request, Exception $exception) {     if ($request->wantsJson()) {   //add Accept: application/json in request         return $this->handleApiException($request, $exception);     } else {         $retval = parent::render($request, $exception);     }      return $retval; } 

Now Handle Api exception

private function handleApiException($request, Exception $exception) {     $exception = $this->prepareException($exception);      if ($exception instanceof \Illuminate\Http\Exception\HttpResponseException) {         $exception = $exception->getResponse();     }      if ($exception instanceof \Illuminate\Auth\AuthenticationException) {         $exception = $this->unauthenticated($request, $exception);     }      if ($exception instanceof \Illuminate\Validation\ValidationException) {         $exception = $this->convertValidationExceptionToResponse($exception, $request);     }      return $this->customApiResponse($exception); } 

After that custom Api handler response

private function customApiResponse($exception) {     if (method_exists($exception, 'getStatusCode')) {         $statusCode = $exception->getStatusCode();     } else {         $statusCode = 500;     }      $response = [];      switch ($statusCode) {         case 401:             $response['message'] = 'Unauthorized';             break;         case 403:             $response['message'] = 'Forbidden';             break;         case 404:             $response['message'] = 'Not Found';             break;         case 405:             $response['message'] = 'Method Not Allowed';             break;         case 422:             $response['message'] = $exception->original['message'];             $response['errors'] = $exception->original['errors'];             break;         default:             $response['message'] = ($statusCode == 500) ? 'Whoops, looks like something went wrong' : $exception->getMessage();             break;     }      if (config('app.debug')) {         $response['trace'] = $exception->getTrace();         $response['code'] = $exception->getCode();     }      $response['status'] = $statusCode;      return response()->json($response, $statusCode); } 

Always add Accept: application/json in your api or json request.

like image 81
rkj Avatar answered Sep 17 '22 17:09

rkj


Laravel is already able to manage json responses by default.

Withouth customizing the render method in app\Handler.php you can simply throw a Symfony\Component\HttpKernel\Exception\HttpException, the default handler will recognize if the request header contains Accept: application/json and will print a json error message accordingly.

If debug mode is enabled it will output the stacktrace in json format too.

Here is a quick example:

<?php  ...  use Symfony\Component\HttpKernel\Exception\HttpException;  class ApiController {     public function myAction(Request $request)     {         try {             // My code...         } catch (\Exception $e) {             throw new HttpException(500, $e->getMessage());         }          return $myObject;     } } 

Here is laravel response with debug off

{     "message": "My custom error" } 

And here is the response with debug on

{     "message": "My custom error",     "exception": "Symfony\\Component\\HttpKernel\\Exception\\HttpException",     "file": "D:\\www\\myproject\\app\\Http\\Controllers\\ApiController.php",     "line": 24,     "trace": [         {             "file": "D:\\www\\myproject\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\ControllerDispatcher.php",             "line": 48,             "function": "myAction",             "class": "App\\Http\\Controllers\\ApiController",             "type": "->"         },         {             "file": "D:\\www\\myproject\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php",             "line": 212,             "function": "dispatch",             "class": "Illuminate\\Routing\\ControllerDispatcher",             "type": "->"         },          ...     ] } 

Using HttpException the call will return the http status code of your choice (in this case internal server error 500)

like image 27
Andrea Mauro Avatar answered Sep 20 '22 17:09

Andrea Mauro