Validasi & Form Request

Setiap kali pengguna mengisi form — entah itu registrasi, checkout, atau edit profil — kamu wajib memvalidasi datanya di server. Tidak peduli seberapa bagus validasi JavaScript di browser, pengguna bisa saja mengakali-nya.

Di PHP Native, kita menulis validasi manual dengan if-else yang panjang. Di Laravel? Cukup satu baris.

1. Validasi Langsung di Controller

Cara paling cepat memvalidasi input di Laravel:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ProdukController extends Controller
{
    public function store(Request $request)
    {
        // Validasi — otomatis redirect + pesan error jika gagal!
        $validated = $request->validate([
            'nama'      => 'required|string|max:255',
            'harga'     => 'required|numeric|min:1000',
            'deskripsi' => 'nullable|string|max:1000',
            'gambar'    => 'required|image|max:2048', // Maks 2MB
        ]);

        // Kalau sampai sini, artinya data sudah VALID
        Produk::create($validated);

        return redirect('/produk')->with('success', 'Produk berhasil ditambahkan!');
    }
}

Apa yang terjadi jika validasi gagal?

  • Laravel otomatis redirect kembali ke halaman form
  • Pesan error tersedia di variabel $errors
  • Input lama tersedia via old('nama_field')

2. Menampilkan Error di Blade

Di file Blade (tampilan), kamu bisa menampilkan error validasi:

<!-- resources/views/produk/create.blade.php -->

<form method="POST" action="/produk" enctype="multipart/form-data">
    @csrf

    <div>
        <label for="nama">Nama Produk:</label>
        <input type="text" name="nama" id="nama" value="{{ old('nama') }}">

        {{-- Menampilkan error untuk field "nama" --}}
        @error('nama')
            <p style="color: red;">{{ $message }}</p>
        @enderror
    </div>

    <div>
        <label for="harga">Harga (Rp):</label>
        <input type="number" name="harga" id="harga" value="{{ old('harga') }}">

        @error('harga')
            <p style="color: red;">{{ $message }}</p>
        @enderror
    </div>

    <div>
        <label for="deskripsi">Deskripsi:</label>
        <textarea name="deskripsi" id="deskripsi">{{ old('deskripsi') }}</textarea>
    </div>

    <button type="submit">Simpan Produk</button>
</form>

{{-- Atau tampilkan SEMUA error sekaligus --}}
@if ($errors->any())
    <div style="background: #fee; padding: 1rem; border-radius: 8px;">
        <strong>Oops! Ada masalah:</strong>
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
old() Mengembalikan Input Lama

Fungsi old('nama') mengembalikan nilai yang diketik user sebelumnya. Jadi kalau validasi gagal, user tidak perlu mengetik ulang semua field dari awal!

3. Aturan Validasi yang Sering Dipakai

Berikut aturan validasi bawaan Laravel yang paling berguna:

AturanFungsiContoh
requiredWajib diisi'nama' => 'required'
stringHarus berupa teks'nama' => 'string'
numericHarus berupa angka'harga' => 'numeric'
emailHarus format email valid'email' => 'email'
min:NMinimal N karakter/nilai'password' => 'min:8'
max:NMaksimal N karakter/nilai'nama' => 'max:255'
unique:tabel,kolomTidak boleh duplikat di DB'email' => 'unique:users,email'
confirmedHarus sama dengan field _confirmation'password' => 'confirmed'
imageHarus file gambar (jpg, png, dll)'foto' => 'image'
nullableBoleh kosong'bio' => 'nullable'
in:a,b,cHarus salah satu dari daftar'status' => 'in:aktif,nonaktif'

4. Form Request (Validasi yang Lebih Rapi)

Jika validasinya banyak dan kompleks, controller akan jadi berantakan. Solusinya: buat Form Request — sebuah class khusus untuk validasi.

# Buat Form Request via Artisan
php artisan make:request StoreProdukRequest

File baru akan muncul di app/Http/Requests/StoreProdukRequest.php:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreProdukRequest extends FormRequest
{
    /**
     * Apakah user boleh melakukan request ini?
     */
    public function authorize(): bool
    {
        return true; // Untuk sekarang, izinkan semua
    }

    /**
     * Aturan validasi.
     */
    public function rules(): array
    {
        return [
            'nama'      => 'required|string|max:255',
            'harga'     => 'required|numeric|min:1000',
            'deskripsi' => 'nullable|string|max:1000',
            'gambar'    => 'required|image|max:2048',
            'kategori'  => 'required|exists:kategoris,id',
        ];
    }

    /**
     * Pesan error custom dalam Bahasa Indonesia.
     */
    public function messages(): array
    {
        return [
            'nama.required'  => 'Nama produk harus diisi.',
            'harga.min'      => 'Harga minimal Rp 1.000.',
            'gambar.max'     => 'Ukuran gambar maksimal 2MB.',
            'kategori.exists' => 'Kategori yang dipilih tidak valid.',
        ];
    }
}

Sekarang controller jadi sangat bersih:

<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreProdukRequest;

class ProdukController extends Controller
{
    public function store(StoreProdukRequest $request)
    {
        // Validasi SUDAH otomatis berjalan sebelum masuk ke sini!
        $validated = $request->validated();

        Produk::create($validated);

        return redirect('/produk')->with('success', 'Produk berhasil ditambahkan!');
    }
}
Keamanan Mass Assignment

Jangan pernah gunakan $request->all() langsung di Model::create(). Gunakan $request->validated() atau $request->only(['nama', 'harga']) untuk memastikan hanya field yang sudah divalidasi yang masuk ke database. Ini mencegah serangan Mass Assignment — di mana pengguna nakal menambahkan field tersembunyi (seperti is_admin=1) melalui form.

5. Perbandingan: PHP Native vs Laravel

AspekPHP NativeLaravel
ValidasiTulis if-else satu per satuSatu array aturan
Error MessagesBuat variabel array manual$errors otomatis tersedia di Blade
Input LamaSimpan manual di sessionold('field') otomatis
Custom MessagesHardcode di masing-masing ifMethod messages() di Form Request
Lokasi KodeTercampur di file yang samaTerpisah rapi di Form Request class

Selanjutnya

Data sudah divalidasi? Bagus! Tapi siapa yang mengirim data itu? Kamu butuh sistem login. Lanjut ke Otentikasi Laravel → untuk belajar membuat fitur registrasi dan login dalam hitungan menit.

Troubleshooting Form Laravel

Kalau form Laravel kamu gagal submit, error tidak muncul di Blade, atau malah berakhir di halaman 419, baca juga: