環境
Laravel v9.5.1 (PHP v8.1.3)
エラーレスポンスの統一
LaravelのデフォルトのままだとバリデーションエラーとHTTPエラーでエラーレスポンスの形が異なっているため統一する。
エラーメッセージは下記の形で返るようにしたい。
{
"message" => "Forbidden"
}
①Handlerに登録
HandlerにバリデーションエラーとHTTPエラーそれぞれのエラーレスポンスの処理を登録。
app/Exceptions/Handler.php
...
public function register()
{
$this->renderable(function (HttpException $e, $request) {
$message = $e->getMessage();
switch ($e->getStatusCode()) {
case 401:
$message = __('Unauthorized');
break;
case 403:
$message = __('Forbidden');
break;
case 404:
$message = __('Not Found');
break;
case 500:
$message = __('Internal Server Error');
break;
default:
return;
}
$errorMessage = [
'message' => $message,
];
return (new ErrorResource($errorMessage))->response()->setStatusCode($e->getStatusCode());
});
$this->renderable(function (ValidationException $e, $request) {
if ($request->is('api/*')) {
$message = $e->getMessage();
if ($e->errors()) {
$message = Arr::flatten($e->errors())[0];
};
$errorMessage = [
'message' => $message,
];
return (new ErrorResource($errorMessage))->response()->setStatusCode($e->status);
};
});
}
②ErrorResourceを作成
他のAPIをAPIリソースを使ってJsonで返していたため、そこも統一すべくErrorResource
を作成。
ほとんどファイル作成時のままでいいが、public static $wrap = null;
でデータラッパーをなしにすることで、やりたいメッセージの形にする。
class ErrorResource extends JsonResource
{
public function toArray($request)
{
return parent::toArray($request);
}
public static $wrap = null;
}
③アプリ独自のエラーにもErrorResourceをあてる
class NotSettingProfileException extends Exception
{
public function __construct()
{
parent::__construct('プロフィールを設定してください', 400);
}
public function render($request)
{
$errorMessage = [
'message' => 'プロフィールを設定してください'
];
return (new ErrorResource($errorMessage))->response()->setStatusCode(400);
}
}
参考