WebTech Interaktif XI RPL

Laravel · Bab 7

Lab 4: Form, CSRF & Validasi

Membuat form tambah produk yang aman dengan token @csrf, memvalidasi input di sisi server, menampilkan pesan galat per kolom, lalu menyimpan data dengan Eloquent.

Di lab ini katalog Smart Retail App bisa diisi: kamu membuat form tambah produk, memvalidasi setiap kolom di server, dan menyimpan data yang lolos validasi. Contoh kode memakai studi kasus perpustakaan (books dan authors); terapkan polanya ke produk dan kategori sesuai aturan validasi di Alur Langkah.

Alur Langkah

  1. Di controller produk, tambahkan method create() yang mengambil semua kategori dan mengirimkannya ke view form.
  2. Tambahkan method store(Request $request) yang memvalidasi product_code (wajib, unik, maks. 10 karakter), name (wajib, 3–100 karakter), category_id (wajib, harus ada di tabel kategori), price (wajib, angka, min. 500), dan stock (wajib, bilangan bulat, min. 0), dengan pesan kustom untuk kode kembar, kategori tidak valid, dan harga terlalu kecil. Setelah itu simpan data dan redirect ke katalog dengan pesan sukses.
  3. Buat view create.blade.php berisi form: kode produk, dropdown kategori, nama, harga, stok awal, serta tombol Cancel dan Save Product.
  4. Buka halaman katalog, klik Add Product, lalu coba kirim form kosong, kode kembar, dan data yang benar.

Method create() & store()

create() hanya menyiapkan data untuk form, misalnya daftar penulis untuk dropdown:

public function create()
{
    $authors = Author::all();
    return view('books.create', compact('authors'));
}

Validasi Server-Side

Validasi di server adalah pertahanan utama. Validasi di peramban (atribut HTML required) mudah dilewati, sedangkan $request->validate selalu berjalan sebelum data menyentuh database. Jika ada aturan yang gagal, Laravel otomatis mengembalikan pengguna ke form beserta pesan galat dan input sebelumnya.

public function store(Request $request)
{
    $validated = $request->validate([
        'isbn'      => 'required|unique:books,isbn|max:13',
        'title'     => 'required|min:3|max:100',
        'author_id' => 'required|exists:authors,id',
        'price'     => 'required|numeric|min:500',
        'stock'     => 'required|integer|min:0',
    ], [
        'isbn.unique' => 'ISBN sudah terdaftar!',
    ]);

    Book::create($validated);

    return redirect()->route('books.index')->with('success', 'Buku berhasil ditambahkan!');
}
AturanArti
requiredWajib diisi
unique:tabel,kolomNilai belum pernah dipakai di kolom tersebut
exists:tabel,kolomNilai harus ada di tabel lain (mencegah ID kategori palsu)
numericHarus angka (boleh desimal)
integerHarus bilangan bulat
min:n / max:nBatas nilai untuk angka, atau batas panjang untuk teks

Array kedua berisi pesan kustom dengan format 'kolom.aturan' => 'pesan'. Hasil validasi ($validated) langsung disimpan dengan Model::create — karena itulah semua kolomnya harus terdaftar di $fillable. Terakhir, ->with('success', ...) mengirim pesan yang ditampilkan kotak sukses di layout.

Form Blade: @csrf, old() & @error

<form action="{{ route('books.store') }}" method="POST">
    @csrf

    <label class="form-label">Judul Buku</label>
    <input type="text" name="title"
           class="form-control @error('title') is-invalid @enderror"
           value="{{ old('title') }}">
    @error('title')
        <div class="invalid-feedback">{{ $message }}</div>
    @enderror

    <label class="form-label">Penulis</label>
    <select name="author_id" class="form-select @error('author_id') is-invalid @enderror">
        <option value="">-- Pilih Penulis --</option>
        @foreach($authors as $author)
            <option value="{{ $author->id }}" {{ old('author_id') == $author->id ? 'selected' : '' }}>
                {{ $author->name }}
            </option>
        @endforeach
    </select>

    <button type="submit" class="btn btn-primary">Simpan</button>
</form>
  • @csrf menyisipkan token tersembunyi yang wajib ada di setiap form POST (Bab 2).
  • old('title') mengisi ulang input dengan nilai sebelumnya ketika validasi gagal, sehingga pengguna tidak perlu mengetik ulang. Bentuk old('stock', 0) memberi nilai awal.
  • @error('title') … @enderror hanya tampil bila kolom itu gagal validasi; $message berisi pesan galatnya.
  • Kelas Bootstrap is-invalid memberi bingkai merah dan memunculkan invalid-feedback.

Hasil yang Diharapkan

Form kosong atau kode produk kembar ditolak dengan pesan merah di bawah kolom yang salah, dan isian lain tetap terisi. Data yang benar tersimpan, lalu kamu kembali ke katalog dengan kotak pesan hijau dan produk baru di baris teratas.