Memvalidasi input secara menyeluruh: aturan validasi, custom rules, Validator manual, dan Form Requests, lalu menangani error dengan Exception Handler, custom exceptions, dan halaman HTTP error yang ramah pengguna.

Input user adalah musuh terbesar aplikasi web: data kosong, format salah, email duplikat, dan serangan injeksi semuanya masuk lewat input. Di episode 5 kita sudah mencicipi $request->validate(); di episode ini kita dalami seluruh kemampuan validasi Laravel, lalu beralih ke sisi lain yang sering diabaikan: penanganan error yang baik.
Aplikasi yang matang tidak hanya mencegah data buruk masuk — ia juga tahu persis apa yang terjadi saat sesuatu gagal, dan menyampaikan kegagalan itu ke user dengan cara yang tidak membingungkan.
Laravel punya lebih dari 50 aturan bawaan. Yang paling sering dipakai:
| Aturan | Fungsi |
|---|---|
required, nullable | Wajib ada / boleh kosong |
string, integer, boolean | Tipe data |
email, url, date | Format spesifik |
min:8, max:255 | Panjang minimum/maksimum |
confirmed | Cocok dengan field _confirmation |
unique:posts,slug | Harus unik di tabel posts kolom slug |
exists:users,id | Harus ada di tabel users |
image, file, mimes:pdf | Upload file |
in:draft,published | Harus salah satu nilai |
$validated = $request->validate([
'title' => ['required', 'string', 'max:255'],
'slug' => ['required', 'string', 'regex:/^[a-z0-9-]+$/'],
'email' => ['required', 'email', 'unique:users,email'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'status' => ['required', 'in:draft,published'],
'cover' => ['nullable', 'image', 'max:2048'],
]);unique bisa dikecualikan untuk record yang sedang di-update: unique:posts,slug, + $post->id.
Saat aturan bawaan tidak cukup, buat rule sendiri — dua cara:
'handle' => ['required', function (string $attribute, mixed $value, Closure $fail) {
if (!str_starts_with($value, 'devvnull-')) {
$fail("Field {$attribute} harus diawali 'devvnull-'.");
}
}]php artisan make:rule Uppercase<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class Uppercase implements ValidationRule
{
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if ($value !== mb_strtoupper($value)) {
$fail('The :attribute field must be uppercase.');
}
}
}Rule class bisa diuji secara unit — pola yang lebih rapi daripada closure yang menumpuk di Form Request.
Saat validasi dipakai di luar request HTTP (misalnya di command atau service), pakai Validator langsung:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($payload, [
'name' => 'required|string|max:100',
]);
if ($validator->fails()) {
$errors = $validator->errors();
// tangani error tanpa redirect
}Ini memberi kontrol penuh atas alur tanpa bergantung pada redirect otomatis dari request HTTP.
Ketika exception dilempar, Laravel menyerahkannya ke Exception Handler (bootstrap/app.php di Laravel 11+). Di sini kalian bisa kustomisasi respons untuk exception tertentu:
->withExceptions(function (Exceptions $exceptions) {
$exceptions->render(function (NotFoundHttpException $e, Request $request) {
if ($request->is('api/*')) {
return response()->json([
'message' => 'Resource tidak ditemukan.',
], 404);
}
return response()->view('errors.404', [], 404);
});
})Pola ini sangat berguna untuk membedakan respons JSON (API) dan HTML (web) terhadap error yang sama.
Untuk kondisi error spesifik aplikasi, buat exception sendiri:
php artisan make:exception InsufficientBalancethrow new InsufficientBalance('Saldo tidak mencukupi untuk transaksi ini.');Custom exception memakai mekanisme yang sama dengan exception bawaan — bisa di-render, di-log, dan diuji secara terpisah.
Laravel menyediakan halaman error standar (403, 404, 500, 503). Untuk tampilan yang sesuai brand aplikasi, publish templatenya:
php artisan vendor:publish --tag=laravel-errorsFile dihasilkan di resources/views/errors/ — 404.blade.php, 500.blade.php, dan seterusnya. Variabel $exception tersedia di view untuk menampilkan detail. Pastikan halaman 500 tidak membocorkan stack trace (jaga APP_DEBUG=false di production).
Warning
Di production, APP_DEBUG wajib false — jika true, error apa pun menampilkan stack trace dan isi .env ke pengunjung. Ini salah satu kebocoran informasi paling umum di aplikasi Laravel yang tidak sengaja ter-deploy dengan debug aktif.
Inti yang harus dibawa pulang:
required, email, unique, confirmed, in, dan regex.Validator::make() untuk konteks non-HTTP.APP_DEBUG=false di production — jangan pernah bocorkan stack trace.Di episode 13 selanjutnya kita akan membahas query optimization & caching — indexing, pemilihan kolom dengan select, chunking dengan chunk()/lazy(), EXPLAIN, facade Cache, Cache::remember, dan fitur baru Cache::touch() di Laravel 13. Sampai jumpa di episode 13!