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エラーを処理するための良い方法ですか?
ありがとう。
これを試して、プロジェクトで使用しました(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;
}
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);
}
常にAccept: application/json
apiまたはjsonリクエストで。
Laravelはすでにデフォルトでjson応答を管理できます。
App\Handler.phpのrenderメソッドをカスタマイズせずにSymfony\Component\HttpKernel\Exception\HttpExceptionをスローするだけで、デフォルトハンドラーはリクエストヘッダーにAccept:application/jsonが含まれているかどうかを認識します。それに応じてJSONエラーメッセージを出力します。
デバッグモードが有効になっている場合、json形式でスタックトレースも出力されます。
以下に簡単な例を示します。
<?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)
私の意見では、シンプルに保ちます。
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ステータスコードを渡すことで、柔軟性を高めることができます。