任何人都知道在Laravel中处理错误的最佳方法是什么,是否有任何规则或要遵循的东西?
当前我正在这样做:
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.");
}
}
setStatusCode和responseWithError来自我的控制器之父:
public function setStatusCode($statusCode)
{
$this->statusCode = $statusCode;
return $this;
}
public function responseWithError ($message )
{
return $this->response([
'error' => [
'message' => $message,
'status_code' => $this->getStatusCode()
]
]);
}
但这是处理API错误的好方法,我在网络上看到了一些不同的处理错误的方法,什么是最好的?
谢谢。
答案 0 :(得分:10)
尝试一下,我已经在我的项目中使用了它(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异常
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);
}
自定义Api处理程序响应
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);
}
始终在您的api或json请求中添加Accept: application/json
。
答案 1 :(得分:2)
Laravel在默认情况下已经能够管理json响应。
无需自定义app \ Handler.php中的render方法,您可以简单地抛出Symfony \ Component \ HttpKernel \ Exception \ HttpException,默认处理程序将识别请求标头是否包含接受:application / json ,并将相应地显示json错误消息。
如果启用了调试模式,它也会以json格式输出stacktrace。
这是一个简单的例子:
<?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;
}
}
这是关闭调试后的laravel响应
{
"message": "My custom error"
}
这是调试打开的响应
{
"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": "->"
},
...
]
}
使用HttpException,该调用将返回您选择的http状态代码(在这种情况下,内部服务器错误500)
答案 2 :(得分:2)
我认为最好修改在 app / Exceptions / Handler.php 中实现的现有行为,而不是对其进行覆盖。
您可以修改parent::render($request, $exception);
返回的JSONResponse并添加/删除数据。
示例实现:
app / Exceptions / Handler.php
use Illuminate\Support\Arr;
// ... existing code
public function render($request, Exception $exception)
{
if ($request->is('api/*')) {
$jsonResponse = parent::render($request, $exception);
return $this->processApiException($jsonResponse);
}
return parent::render($request, $exception);
}
protected function processApiException($originalResponse)
{
if($originalResponse instanceof JsonResponse){
$data = $originalResponse->getData(true);
$data['status'] = $originalResponse->getStatusCode();
$data['errors'] = [Arr::get($data, 'exception', 'Something went wrong!')];
$data['message'] = Arr::get($data, 'message', '');
$originalResponse->setData($data);
}
return $originalResponse;
}
答案 3 :(得分:1)
我认为这很简单。
返回带有HTTP错误代码和自定义消息的响应。
return response()->json(['error' => 'You need to add a card first'], 500);
或者,如果您想引发捕获的错误,可以执行以下操作:
try {
// some code
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
您甚至可以使用它来发送成功的回复:
return response()->json(['activeSubscription' => $this->getActiveSubscription()], 200);
这样,无论哪个服务使用您的API,它都可以期望对相同的请求收到相同的响应。
您还可以看到通过传递HTTP状态代码来实现此功能的灵活性。
答案 4 :(得分:1)
使用来自@RKJ的一些最佳答案,我以这种方式处理了错误:
打开“ Illuminate \ Foundation \ Exceptions \ Handler” 类,然后搜索名为“ convertExceptionToArray” 的方法。此方法将HTTP异常转换为要显示为响应的数组。在这种方法中,我只调整了一小段代码,这些代码不会影响松耦合。
因此,将 convertExceptionToArray 方法替换为此
protected function convertExceptionToArray(Exception $e, $response=false)
{
return config('app.debug') ? [
'message' => $e->getMessage(),
'exception' => get_class($e),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => collect($e->getTrace())->map(function ($trace) {
return Arr::except($trace, ['args']);
})->all(),
] : [
'message' => $this->isHttpException($e) ? ($response ? $response['message']: $e->getMessage()) : 'Server Error',
];
}
现在导航到 App \ Exceptions \ Handler 类,并将以下代码粘贴在 render 方法上方:
public function convertExceptionToArray(Exception $e, $response=false){
if(!config('app.debug')){
$statusCode=$e->getStatusCode();
switch ($statusCode) {
case 401:
$response['message'] = 'Unauthorized';
break;
case 403:
$response['message'] = 'Forbidden';
break;
case 404:
$response['message'] = 'Resource Not Found';
break;
case 405:
$response['message'] = 'Method Not Allowed';
break;
case 422:
$response['message'] = 'Request unable to be processed';
break;
default:
$response['message'] = ($statusCode == 500) ? 'Whoops, looks like something went wrong' : $e->getMessage();
break;
}
}
return parent::convertExceptionToArray($e,$response);
}
基本上,我们重写了convertExceptionToArray方法,准备了响应消息,并通过将响应作为参数传递来调用了父方法。
注意:此解决方案不适用于身份验证/验证错误,但是在大多数情况下,这两种错误都由Laravel使用正确的人类可读响应消息来妥善管理。
答案 5 :(得分:1)
对我来说,最好的方法是使用特定的 Exception 进行 API 响应。
如果您使用 Laravel 版本 > 5.5,您可以使用 report()
和 render()
方法create your own exception。使用命令:
php artisan make:exception AjaxResponseException
它将在以下位置创建 AjaxResponseException.php: app/Exceptions/
之后用你的逻辑填充它。例如:
/**
* Report the exception.
*
* @return void
*/
public function report()
{
\Debugbar::log($this->message);
}
/**
* Render the exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @return JsonResponse|Response
*/
public function render($request)
{
return response()->json(['error' => $this->message], $this->code);
}
现在,您可以在具有 ...Controller
功能的 try/catch
中使用它。
例如以您的方式:
public function store(Request $request)
{
try{
$plate = Plate::create($request->all());
if ($plate) {
return $this->response($this->plateTransformer->transform($plate));
}
throw new AjaxResponseException("Plate wasn't created!", 404);
}catch (AjaxResponseException $e) {
throw new AjaxResponseException($e->getMessage(), $e->getCode());
}
}
这足以使您的代码更易于阅读、美观且有用。
最好的问候!
答案 6 :(得分:0)
在您的handler.php中,这应该可以处理404异常。
public function render($request, Throwable $exception ){
if ($exception instanceof ModelNotFoundException) {
return response()->json([
'error' => 'Data not found'
], 404);
}
return parent::render($request, $exception);
}
答案 7 :(得分:-1)
处理Api错误的好方法是在render方法中的app \ Exceptions \ Hendler.php中处理此错误。