Pendahuluan — pintu sudah ada, siapa yang menjaga?
Di Laravel Routing & JSON (#56) kamu sudah punya pintu HTTP yang menjawab JSON. Artikel ini adalah #57 (ini) — langkah kedua stack Laravel di Seri 4.
Ide barunya: data yang masuk lewat pintu bisa kotor (kosong, salah tipe, tidak masuk akal). Kita butuh penjaga yang memeriksa dulu — baru boleh diproses.
Awam: bayangkan loket perpustakaan. Pengunjung membawa formulir pinjam. Petugas (penjaga) cek: nama terisi? tahun masuk akal? Kalau tidak, formulir dikembalikan dengan catatan — bukan langsung masuk ke rak.
Prasyarat: sudah baca Laravel Routing & JSON (#56) — paham route, JSON, dan status 200/404. Domain tetap perpustakaan mini. Pakai Laravel 11+ — sintaks validasi di sini berlaku di versi modern.
Istilah — Request, validasi, Form Request
| Istilah | Arti awam | Contoh di artikel ini |
|---|---|---|
| Request | Paket data yang masuk lewat pintu (judul, tahun, dll.) | {"judul":"...","tahun":2024} |
| Validasi | Cek: data wajib ada, tipe benar, rentang masuk akal | Judul tidak kosong; tahun 1900-2100 |
| Form Request | Kelas Laravel khusus yang menyimpan aturan penjaga | StoreBukuRequest |
| POST | Cara mengetuk pintu: “kirim data baru/ubah” (bukan hanya minta baca) | POST /api/buku + JSON isi buku |
| Status 422 | “Data kamu tidak diterima” (bukan “pintu tidak ada”) | 422 — isian ditolak |
Jangan hafal semua status dulu. Cukup tiga: 200/201 (sukses), 404 (tidak ketemu), 422 (data kotor).
Validasi dulu — tanpa framework
Kenapa belum langsung Form Request? Karena ide “cek dulu, baru proses” bisa dirasakan di PHP biasa. Kalau ide-nya sudah “klik”, cuplikan Laravel nanti terasa seperti bungkus yang sama.
<?php
$input = [
"judul" => "",
"tahun" => 2024,
];
$errors = [];
if (! isset($input["judul"]) || trim((string) $input["judul"]) === "") {
$errors["judul"] = "Judul wajib diisi";
}
if (! isset($input["tahun"]) || ! is_numeric($input["tahun"])) {
$errors["tahun"] = "Tahun harus angka";
} elseif ((int) $input["tahun"] < 1900 || (int) $input["tahun"] > 2100) {
$errors["tahun"] = "Tahun di luar rentang";
}
header("Content-Type: application/json; charset=utf-8");
if ($errors !== []) {
http_response_code(422);
echo json_encode(["pesan" => "Data tidak valid", "errors" => $errors], JSON_UNESCAPED_UNICODE), PHP_EOL;
exit;
}
http_response_code(201);
echo json_encode(["ok" => true, "buku" => $input], JSON_UNESCAPED_UNICODE), PHP_EOL;
Output:
{"pesan":"Data tidak valid","errors":{"judul":"Judul wajib diisi"}}
Awam: status 422 artinya “pintu ketemu, tapi isian ditolak”. Bedakan dari 404 (pintu/data tidak ada) di Laravel Routing & JSON (#56).
Kalau data bersih — status 201
Isian lengkap dan masuk akal boleh “diterima”:
<?php
$input = [
"judul" => "Belajar PHP",
"tahun" => 2024,
];
$errors = [];
if (! isset($input["judul"]) || trim((string) $input["judul"]) === "") {
$errors["judul"] = "Judul wajib diisi";
}
if (! isset($input["tahun"]) || ! is_numeric($input["tahun"])) {
$errors["tahun"] = "Tahun harus angka";
} elseif ((int) $input["tahun"] < 1900 || (int) $input["tahun"] > 2100) {
$errors["tahun"] = "Tahun di luar rentang";
}
header("Content-Type: application/json; charset=utf-8");
if ($errors !== []) {
http_response_code(422);
echo json_encode(["pesan" => "Data tidak valid", "errors" => $errors], JSON_UNESCAPED_UNICODE), PHP_EOL;
exit;
}
http_response_code(201);
echo json_encode(["ok" => true, "buku" => $input], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), PHP_EOL;
Output:
{
"ok": true,
"buku": {
"judul": "Belajar PHP",
"tahun": 2024
}
}
Awam: 201 sering dipakai untuk “berhasil membuat sesuatu baru” (misalnya buku baru). Kalau bingung, anggap dulu “sukses” — angka pastinya bisa dirapikan nanti.
Laravel — Request di route
Di project Laravel, cuplikan tipikal memakai $request->validate(...). File ini bukan dijalankan dengan php file.php — ia hidup di dalam project Laravel:
<?php
// Cuplikan Laravel (bukan file mandiri) — ide sama dengan validasi PHP di atas.
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::post('/api/buku', function (Request $request) {
$data = $request->validate([
'judul' => 'required|string|max:120',
'tahun' => 'required|integer|min:1900|max:2100',
]);
return response()->json(['ok' => true, 'buku' => $data], 201);
});
Awam:
Request $request= paket data masuk (isi formulir / isi JSON)validate([...])= daftar aturan penjaga- Teks aturan dipisah
|:required= wajib,string= teks,integer= bilangan bulat,max:120/min:1900= batas panjang/nilai - Kalau gagal, Laravel biasanya menjawab status
422+ daftar error (tanpa kamu tulis manual)
Form Request — aturan pindah ke kelas
Kalau aturan makin panjang, jangan biarkan semuanya menumpuk di file route. Pindahkan ke kelas Form Request:
<?php
// Cuplikan Laravel — kelas penjaga (bukan file mandiri).
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreBukuRequest extends FormRequest
{
public function rules(): array
{
return [
'judul' => 'required|string|max:120',
'tahun' => 'required|integer|min:1900|max:2100',
];
}
}
<?php
// Cuplikan Laravel — pakai Form Request di route.
use App\Http\Requests\StoreBukuRequest;
use Illuminate\Support\Facades\Route;
Route::post('/api/buku', function (StoreBukuRequest $request) {
$data = $request->validated();
return response()->json(['ok' => true, 'buku' => $data], 201);
});
Awam: validated() hanya mengembalikan field yang sudah lolos penjaga. Data kotor tidak ikut “nyelonong”.
Pola Dasar — Request & validasi
-
1
Tahu data apa yang masuk Misalnya
juduldantahununtuk buku baru. -
2
Tulis aturan penjaga Wajib? String? Angka? Rentang tahun?
-
3
Tolak dengan status jujur Data kotor ->
422. Jangan pura-pura200. -
4
Pakai data yang sudah bersih
validated()/ array yang lolos cek — bukan data mentah dari request. -
5
Baru pikir penyimpanan & struktur kode Berikutnya: Controller, Service & Eloquent (#58) — pengatur kode, layanan, dan penyimpanan data setelah penjaga berdiri.
Kode lengkap — laravel_request_validasi_demo.php
Simpan dan jalankan: php laravel_request_validasi_demo.php. Ini meniru penjaga validasi tanpa server Laravel — supaya ide-nya terasa dulu.
Awam: fungsi validasiBuku() mengembalikan daftar kesalahan (kosong = lolos). Baris mixed $data artinya data bisa bermacam bentuk — tidak perlu dihafal. Fokus ke alur: cek -> tolak/terima.
<?php
/**
* Demo ide Request & validasi (Seri 4 #57).
* Di Laravel, ide yang sama hidup di Request::validate / Form Request.
*/
declare(strict_types=1);
function kirimJson(mixed $data, int $status = 200): void
{
http_response_code($status);
header("Content-Type: application/json; charset=utf-8");
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), PHP_EOL;
}
function validasiBuku(array $input): array
{
$errors = [];
if (! isset($input['judul']) || trim((string) $input['judul']) === '') {
$errors['judul'] = 'Judul wajib diisi';
}
if (! isset($input['tahun']) || ! is_numeric($input['tahun'])) {
$errors['tahun'] = 'Tahun harus angka';
} elseif ((int) $input['tahun'] < 1900 || (int) $input['tahun'] > 2100) {
$errors['tahun'] = 'Tahun di luar rentang';
}
return $errors;
}
function demo(): void
{
echo "=== POST kotor (judul kosong) ===", PHP_EOL;
$kotor = ['judul' => '', 'tahun' => 2024];
$errors = validasiBuku($kotor);
if ($errors !== []) {
kirimJson(['pesan' => 'Data tidak valid', 'errors' => $errors], 422);
}
echo "=== POST bersih ===", PHP_EOL;
$bersih = ['judul' => 'Belajar PHP', 'tahun' => 2024];
$errors = validasiBuku($bersih);
if ($errors === []) {
kirimJson(['ok' => true, 'buku' => $bersih], 201);
}
}
demo();
Output yang diharapkan:
=== POST kotor (judul kosong) ===
{
"pesan": "Data tidak valid",
"errors": {
"judul": "Judul wajib diisi"
}
}
=== POST bersih ===
{
"ok": true,
"buku": {
"judul": "Belajar PHP",
"tahun": 2024
}
}
Kesalahan umum
| Gejala | Penyebab tipikal | Perbaikan |
|---|---|---|
| Data kotor tetap diproses | Langsung pakai input mentah | Validasi dulu; pakai hasil yang sudah bersih |
| Gagal validasi tapi status 200 | Lupa status error | Pakai 422 (atau biarkan Laravel yang mengurus) |
| Bingung 404 vs 422 | Semua error dianggap “tidak ketemu” | 404 = tidak ada; 422 = ada tapi isian ditolak |
| Aturan menumpuk di route | Semua cek ditumpuk di dalam file route | Pindah ke Form Request (#57 (ini)) |
| Langsung loncat database | Mau simpan sebelum penjaga siap | Rapatkan validasi dulu, baru penyimpanan nanti |
Latihan singkat
- Di demo PHP, tambah aturan: judul maksimal 40 karakter; uji dengan judul yang terlalu panjang.
- Ubah tahun jadi
1800dan pastikan output menampilkan error rentang (bukan sukses). - Di cuplikan Laravel, tambah field
penuliswajib string di aturanvalidate.
FAQ singkat
Harus install Laravel dulu?
Untuk memahami ide: demo PHP di atas sudah cukup. Untuk latihan framework: buat project Laravel 11+ lalu tempel cuplikan route / Form Request.
Kenapa tidak cukup cek di tampilan browser saja?
Tampilan di browser (sering disebut frontend) bisa dilewati. Penjaga di server (API) tetap wajib — itu tempat keputusan yang bisa dipercaya.
Apa bedanya $request->validate dan Form Request?
Secara awam: sama-sama penjaga. Form Request memindahkan aturan ke kelas sendiri supaya file route / pengatur kode tetap tipis dan rapi.
Lanjut ke mana?
Berikutnya: Controller, Service & Eloquent (#58) — pengatur kode, layanan, dan penyimpanan data setelah penjaga berdiri.
Kesimpulan & langkah berikutnya
Request = paket masuk. Validasi = cek kelayakan. Form Request = rumah aturan penjaga. Status 422 = “isian ditolak dengan jujur”.
Artikel ini adalah #57 (ini) — penjaga input setelah Laravel Routing & JSON (#56) membuka pintu HTTP.
Seri 4 progress: langkah #57 (ini) · 6/8 menuju Capstone Laravel · stack Laravel 2/5 · prasyarat: Laravel Routing & JSON (#56) LIVE. Berikutnya: Controller, Service & Eloquent (#58).