How Laravel Handles HTTP Errors
- A request hits a non-existent route
- Router throws NotFoundHttpException
- Exception is caught by Handler
- Laravel looks for resources/views/errors/404.blade.php (example)
- Returns an HTTP 404 response with the rendered view
Common Handling
- app/Exceptions/Handler.php : converts exceptions into HTTP responses.
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\Exceptions\ThrottleRequestsException;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Auth\Access\AuthorizationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* The list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*/
public function register(): void
{
$this->reportable(function (Throwable $e) {
//
});
// 403 — Forbidden
$this->renderable(function (AuthorizationException $e, $request) {
if (!$request->expectsJson()) {
return response()->view('errors.403', [], 403);
}
});
// 404 — Not Found
$this->renderable(function (NotFoundHttpException $e, $request) {
if (!$request->expectsJson()) {
return response()->view('errors.404', [], 404);
}
});
// 419 — Page Expired (CSRF Token Mismatch)
$this->renderable(function (TokenMismatchException $e, $request) {
if (!$request->expectsJson()) {
return response()->view('errors.419', [], 419);
}
});
// 429 — Too Many Requests
$this->renderable(function (ThrottleRequestsException $e, $request) {
if (!$request->expectsJson()) {
$retryAfter = $e->getHeaders()['Retry-After'] ?? 60;
return response()->view('errors.429', ['retryAfter' => $retryAfter], 429);
}
});
// 503 — Service Unavailable
$this->renderable(function (ServiceUnavailableHttpException $e, $request) {
if (!$request->expectsJson()) {
return response()->view('errors.503', ['exception' => $e], 503);
}
});
}
public function render($request, Throwable $exception)
{
return parent::render($request, $exception);
}
}
- resources/views/errors/{status_code}.blade.php
# example
# resources\views\errors\404.blade.php
@extends('errors.layout')
@section('error_code', '404')
@section('error_content')
<div class="text-center position-relative z-index-1" style="max-width: 520px;">
{{-- Illustration --}}
<div class="mb-6">
<img src="{{ asset('assets/media/illustrations/unitedpalms-1/18.png') }}"
class="error-illustration theme-light-show" alt="404 Not Found" />
<img src="{{ asset('assets/media/illustrations/unitedpalms-1/18-dark.png') }}"
class="error-illustration theme-dark-show" alt="404 Not Found" />
</div>
{{-- Title --}}
<h1 class="fw-bold fs-2x text-gray-900 mb-3">Page Not Found</h1>
{{-- Description --}}
<p class="text-muted fs-5 mb-8 fw-semibold">
Oops! The page you're looking for doesn't exist.<br>
It may have been moved, deleted, or never existed.
</p>
{{-- Actions --}}
<div class="error-actions d-flex gap-3 justify-content-center flex-wrap">
<a href="{{ url()->previous() !== url()->current() ? url()->previous() : '/' }}"
class="btn btn-light btn-lg fw-bold px-8">
<i class="ki-duotone ki-arrow-left fs-2 me-2">
<span class="path1"></span><span class="path2"></span>
</i>
Go Back
</a>
</div>
</div>
@endsection
Then, just create simple routes to test it.
Route::get('/test-404', function () {
abort(404);
});
Also we can customize error pages by creating the views manually or publishing Laravel’s default templates:
php artisan vendor:publish — tag=laravel-errors
Need help building your app? I’m available for freelance web & Android development — raflizocky.netlify.app
☕ Support my writing: paypal.me/raflizocky · saweria.co/raflizocky
Top comments (0)