مقاله

فرمت خطای API، Handler سفارشی، 422 validation، 404 و 500 — تجربه developer-friendly برای مصرف‌کننده API.

Error Handling در API Laravel — پاسخ JSON یکدست و قابل پیش‌بینی

Error Handling در API Laravel — پاسخ JSON یکدست و قابل پیش‌بینی

API بدون قرارداد خطا = کلاینت crash یا parse error. کاربر موبایل باید بداند 422 یعنی validation، 401 یعنی login دوباره، 500 یعنی «بعداً تلاش کن» — نه stack trace PHP. Laravel 11+ exception handling در bootstrap/app.php متمرکز شده.

فرمت پیشنهادی پاسخ خطا

{
  "message": "Validation failed.",
  "errors": {
    "email": ["The email field is required."]
  }
}

برای خطای عمومی:

{
  "message": "Post not found."
}

Validation 422

Form Request در API:

protected function failedValidation(Validator $validator): void
{
    throw new HttpResponseException(response()->json([
        'message' => __('Validation failed.'),
        'errors' => $validator->errors(),
    ], 422));
}

ModelNotFoundException → 404

Laravel پیش‌فرض برای JSON request 404 JSON می‌دهد — مطمئن شوید Accept: application/json یا route در api.

Handler سفارشی

// bootstrap/app.php
->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (AuthorizationException $e, Request $request) {
        if ($request->expectsJson()) {
            return response()->json(['message' => 'Forbidden.'], 403);
        }
    });

    $exceptions->render(function (Throwable $e, Request $request) {
        if ($request->is('api/*') && ! app()->hasDebugModeEnabled()) {
            return response()->json([
                'message' => 'Server error.',
            ], 500);
        }
    });
})

production: هرگز trace به کلاینت — APP_DEBUG=false.

کدهای status رایج

کدمعنی
200/201موفق / ایجاد
204حذف موفق بدون body
401احراز هویت نشده
403مجوز ندارد — Policy
404منبع نیست
422validation
429rate limit
500خطای سرور

Exception خودتان

class InsufficientStockException extends Exception
{
    public function render(Request $request)
    {
        return response()->json(['message' => 'Insufficient stock.'], 409);
    }
}

Logging

500ها در Sentry/Telescope لاگ — correlation id در header برای پشتیبانی:

$requestId = (string) Str::uuid();
Log::withContext(['request_id' => $requestId]);

یکدستی در کل API

Trait یا base controller error() — همه team یک format. Versioning message را عوض نکند بدون version bump.

جمع‌بندی

قرارداد خطا = بخشی از API spec. با REST و امنیت همراه deploy کنید.

API production-ready