Setiap data yang masuk ke aplikasi kita — form registrasi, query string, body JSON — berasal dari pihak luar yang tidak bisa dipercaya. Aturan keamanan paling dasar di web adalah never trust client input: HTML punya atribut required, JavaScript bisa memeriksa format email, tetapi semua itu mudah dilewati dengan mematikan JavaScript atau mengirim request manual lewat curl. Validasi yang sebenarnya harus terjadi di server, di tempat yang sepenuhnya di bawah kendali kita. Laravel menyediakan sistem validasi yang lengkap untuk kebutuhan tersebut, dan chapter ini membahas fondasi konsepnya: alur kerjanya, hasil validated(), serta konsep error bag.
Alur Kerja Validasi #
Siklus hidup validasi Laravel selalu mengikuti pola yang sama, apa pun tempat kita menulis rules-nya:
- Request masuk membawa data dari pengguna.
- Kode kita memanggil validasi (misalnya
$request->validate([...])). - Laravel memeriksa setiap field terhadap rules yang berlaku.
- Jika lolos semua,
validate()mengembalikan array data yang sudah tersaring dan kode di bawahnya dijalankan. - Jika ada yang gagal, Laravel otomatis membatalkan request — controller tidak pernah tereksekusi — dan menghasilkan error response.
Bentuk error response-nya menyesuaikan jenis request. Untuk request web biasa (form HTML), Laravel me-redirect pengguna kembali ke halaman sebelumnya sambil menyimpan pesan error dan input lama di session. Untuk request yang mengirim header Accept: application/json atau X-Requested-With: XMLHttpRequest, Laravel mengembalikan response JSON berstatus 422.
Mari kita buktikan kedua cabang alur tersebut dengan route sederhana yang memvalidasi tiga field:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function store(Request $request)
{
$validated = $request->validate([
'judul' => 'required|string|min:5',
'isi' => 'required|string',
'email' => 'required|email',
]);
return response()->json($validated);
}
}Ketika input valid, validate() mengembalikan data yang lolos dan kode lanjutan berjalan normal:
POST /posts (Content-Type: application/json)
{"judul": "Belajar Validasi Laravel", "isi": "Isi tulisan pertama kita.", "email": "[email protected]"}Output yang Dihasilkan:
HTTP status: 200
Body: {"judul":"Belajar Validasi Laravel","isi":"Isi tulisan pertama kita.","email":"[email protected]"}Ketika input tidak valid pada request web, hasilnya adalah redirect dengan error di session:
Output yang Dihasilkan:
HTTP status: 302
Redirect ke: http://localhost:8000
errors->all():
- The judul field is required.
- The isi field is required.
- The email field must be a valid email address.Sementara request JSON yang sama menghasilkan response 422 dengan struktur error yang rapi:
{
"message": "The judul field must be at least 5 characters. (and 2 more errors)",
"errors": {
"judul": ["The judul field must be at least 5 characters."],
"isi": ["The isi field is required."],
"email": ["The email field must be a valid email address."]
}
}Perhatikan bahwa perbedaan ini terjadi tanpa satu baris if pun dari kita — mekanisme deteksi dan pemilihan format response ditangani framework secara otomatis.
Data Tersaring: validated() #
Method validate() tidak mengembalikan seluruh input mentah. Nilai baliknya hanya berisi field yang memang kita deklarasikan rules-nya — inilah fungsi validated() dalam bentuk paling sederhana. Pada contoh di atas, misalkan pengguna menyelundupkan field tambahan password_rahasia bersama data form: field tersebut tidak masuk ke hasil validate(), sehingga kode kita tidak pernah menyentuhnya.
Pemanggilan berulang lewat $request->validated() pada controller memberikan array yang sama. Pola ini penting karena mengurangi risiko mass assignment — kita hanya meneruskan data yang benar-benar divalidasi ke Post::create() atau query lainnya. Sebagai contoh konkret: pada pengujian pertama di bawah, request hanya membawa tiga field yang sesuai rules, dan body response 200 memuat tepat ketiga nilai tersebut — tidak kurang, tidak lebih.
Error Bag: Wadah Pesan Error #
Ketika validasi gagal, semua pesan error dikumpulkan ke dalam satu wadah bernama error bag yang di-flash ke session. Bag default berisi pesan per field, dan di sisi view Laravel menyediakan variabel $errors yang selalu tersedia di semua view — kosong jika tidak ada error. Konsep inilah yang membuat directive @error di Blade bisa bekerja tanpa setup tambahan. Kita akan bedah tampilan error ini secara penuh di chapter Error Messages di Blade
.
Di Mana Validasi Boleh Hidup #
Laravel tidak memaksakan satu tempat tunggal untuk menulis rules. Tiga lokasi yang umum:
| Lokasi | Cocok untuk |
|---|---|
Controller ($request->validate()) | Validasi cepat, satu route |
| FormRequest class | Validasi besar, dipakai ulang, mudah diuji |
| Validator facade langsung | Kasus khusus di luar siklus request |
Ketiganya menghasilkan perilaku akhir yang identik — redirect berisi error untuk web, 422 untuk JSON — karena semuanya bermuara pada komponen Validator yang sama di balik layar. Perbedaannya hanya soal letak kode dan seberapa jauh logic validasi tumbuh. Chapter-chapter berikutnya membedah masing-masing lokasi tersebut, dimulai dari rules bawaan yang paling sering dipakai sehari-hari. Referensi lengkapnya selalu tersedia di dokumentasi Validation Laravel
.