Geliştirdiğimiz Handler sınıfı sayesinde;
Bunun yanında ApiResponse helper sınıfı ile;
Bu yaklaşım sayesinde API katmanı daha temiz, bakımı kolay ve ölçeklenebilir hale gelir.
Yeni endpoint eklerken response formatını düşünmek yerine, iş mantığına odaklanmak yeterli olur.
// ===== Handler =====
<?php
namespace App\Exceptions;
use App\Enums\ErrorMessages;
use App\Support\Helpers\ApiResponse;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
/**
* Bu sınıf api isteklerinde oluşabilecek hataları yakalayabilmemiz için yazdığımız exception handler sınıfı
*/
class Handler
{
public static function handle(Request $request, Throwable $exception)
{
return match (true) {
$exception instanceof AuthenticationException => ApiResponse::error(ErrorMessages::Unauthenticated->message(), 401),
$exception instanceof AuthorizationException => ApiResponse::error(ErrorMessages::Unauthorized->message(), 403),
$exception instanceof AccessDeniedHttpException => ApiResponse::error(ErrorMessages::Unauthorized->message(), 403),
$exception instanceof BaseException => ApiResponse::error($exception->getMessage(), $exception->getCode()),
$exception instanceof MethodNotAllowedHttpException => ApiResponse::error(ErrorMessages::MethodNotAllowed->message(), 405),
$exception instanceof ModelNotFoundException => ApiResponse::error(ErrorMessages::ModelNotFound->message(), 404),
$exception instanceof NotFoundHttpException => ApiResponse::error(ErrorMessages::NotFound->message(), 404),
$exception instanceof ValidationException => ApiResponse::error($exception->getMessage(), 422, $exception->errors()),
default => ApiResponse::error(
config('app.debug') ? $exception->getMessage() : ErrorMessages::InternalServerError->message(),
500,
config('app.debug') ? $exception->getTrace() : null
),
};
}
}
// ===== ErrorMessages =====
<?php
namespace App\Enums;
/**
* Bu enum sınıfı api isteklerinde oluşabilecek hataları tanımlamak için kullanılır
*/
enum ErrorMessages: string
{
case TokenExpired = 'token_expired';
case EmailAlreadyVerified = 'email_already_verified';
case InvalidCredentials = 'invalid_credentials';
case Unauthenticated = 'unauthenticated';
case Unauthorized = 'unauthorized';
case MethodNotAllowed = 'method_not_allowed';
case ModelNotFound = 'model_not_found';
case NotFound = 'not_found';
case InternalServerError = 'internal_server_error';
public function message(): string
{
return __('errors.' . $this->value);
}
}
// ===== ApiResponse =====
<?php
namespace App\Support\Helpers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection;
class ApiResponse
{
public static function success(array|JsonResource|null $data = null, ?string $message = null, int $statusCode = 200): JsonResponse
{
return response()->json([
'data' => $data,
'status' => true,
'status_code' => $statusCode,
'message' => $message ?? trans('apiresponse.success_message'),
], $statusCode);
}
public static function item(array|JsonResource|null $data = null, ?string $message = null, int $statusCode = 200)
{
return self::success($data, $message, $statusCode);
}
public static function error(?string $message = null, int $statusCode = 400, array $errors = []): JsonResponse
{
if ($errors === []) {
$errors = [$message];
}
return response()->json([
'status' => false,
'status_code' => $statusCode,
'message' => $message ?? trans('apiresponse.error_message'),
'errors' => $errors,
], $statusCode);
}
public static function created($data = null, ?string $message = null): JsonResponse
{
return self::item($data, $message ?? trans('apiresponse.created_message'), 201);
}
public static function updated($data = null, ?string $message = null): JsonResponse
{
return self::item($data, $message ?? trans('apiresponse.updated_message'));
}
public static function deleted(?string $message = null): JsonResponse
{
return self::item(null, $message ?? trans('apiresponse.deleted_message'));
}
public static function collection(ResourceCollection $collection, ?string $message = null): JsonResponse
{
$return = [
'status' => true,
'status_code' => 200,
'message' => $message ?? trans('apiresponse.success_message'),
'data' => $collection->response()->getData()->data,
];
if (!empty($collection->response()->getData()->meta)) {
$meta = $collection->response()->getData()->meta;
$return['meta'] = $meta;
unset($meta->links);
unset($meta->path);
}
return response()->json($return);
}
}
// ===== NotificationController =====
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\Api\Notifications\NotificationResource;
use App\Support\Helpers\ApiResponse;
use Illuminate\Http\Request;
/**
* Örnek Kullanım
*/
class NotificationController extends Controller
{
public function index(Request $request)
{
$request->validate([
'per_page' => 'integer|nullable',
]);
return ApiResponse::collection(
NotificationResource::collection(
\Auth::user()->notifications()
->paginate($request->per_page ?? 10)
)
);
}
}