Bab 6 — Create: Menambah Siswa dan Validasi
6.1Konsep
Dua method berpasangan
Menambah data selalu butuh dua langkah, dan karena itu dua method:
Formulir dikirim lewat POST, bukan GET, karena ia mengubah data.
Validasi
Di permintaan Bu Rina ada aturan: "nomor HP orang tua wajib ada". Aturan itu ditulis di store() lewat $request->validate([...]):
Kalau ada isian yang kosong, Laravel berhenti di baris itu, mengembalikan pengguna ke halaman sebelumnya, dan menyimpan pesan galatnya. Baris-baris setelahnya tidak dijalankan.
Hasil validate() ($data) berisi hanya kolom yang divalidasi. Itulah yang kita kirim ke create(), bukan seluruh isian mentah.
@csrf: tiket keamanan
Setiap formulir POST di Laravel wajib membawa token rahasia lewat @csrf. Tanpanya, Laravel menolak formulirnya (kode 419 Page Expired). Token itu mencegah situs lain memaksa pengunjungmu mengirim formulir tanpa sadar (serangan CSRF).
Redirect dan pesan sukses
Setelah berhasil menyimpan, kita mengalihkan (redirect) ke daftar, bukan menampilkan halaman langsung. Kalau tidak, menekan tombol refresh akan mengirim formulir yang sama lagi dan membuat siswa ganda. Pesan sukses dibawa lewat ->with('success', '...') dan dibaca di tampilan lewat session('success').
6.2Langkah 1 — Isi create() dan store()
📄 Berkas app/Http/Controllers/SiswaController.php — ganti isi method create() dan store()
Membaca store() baris demi baris:
| Baris | Arti |
|---|---|
$request->validate([...]) |
Periksa isian. Kalau gagal, berhenti di sini dan kembali ke formulir. |
Siswa::create($data) |
Simpan siswa baru ke database (hanya kolom di $fillable). |
redirect()->route('siswa.index') |
Pindah ke daftar siswa. |
->with('success', '...') |
Titipkan pesan sukses untuk satu kali tampil. |
6.3Membaca tampilan formulir
Buka resources/views/siswa/create.blade.php dari Paket Starter. Temukan:
| Potongan | Artinya |
|---|---|
action="{{ route('siswa.store') }}" method="POST" |
Formulir mengirim ke rute siswa.store dengan POST. |
@csrf |
Token keamanan. |
name="nama", name="program_les", name="no_hp" |
Nama kolom yang dikirim. Harus sama dengan kunci di validate() dan $fillable. |
value="{{ old('nama') }}" |
Kalau validasi gagal, isian yang sudah diketik dikembalikan, jadi pengguna tidak mengetik ulang. |
required |
Peramban menolak isian kosong sebelum dikirim. |
{{-- BAB 9: ... --}} |
Sebuah komentar penanda. Kamu akan kembali ke sini di Bab 9. |
6.4💥 Galat yang sengaja dibuat: tanpa @csrf
- Buka
create.blade.php, beri komentar pada baris@csrf(ganti jadi{{-- @csrf --}}), dan simpan. - Buka
/siswa/create, isi data lengkap, klik Simpan. - Kamu akan melihat halaman 419 Page Expired. Tulis di bukumu: menurutmu, apa yang dicegah oleh tiket itu?
- Kembalikan barisnya.
6.5Uji coba
Jalankan php artisan serve lalu coba:
- Klik + Tambah Siswa di daftar, isi nama, program les, nomor HP, klik Simpan. Kamu kembali ke daftar, ada kotak hijau Data siswa berhasil ditambahkan!, dan siswa baru ada di baris atas.
- Kosongkan Nomor HP, klik Simpan. Peramban menolak dan menandai kolom itu.
- Tekan refresh (F5) di halaman daftar setelah menambah. Tidak ada siswa ganda. Kenapa? (Karena redirect.)
6.6Jalankan test
Enam test memeriksa: formulir tampil, data valid tersimpan dan kembali ke daftar, pesan sukses muncul, serta nama, program les, dan nomor HP kosong masing-masing ditolak dan tidak ada data yang masuk. Harapannya: Tests: 6 passed.
Titik periksa Bab 6
Centang setiap butir yang sudah kamu selesaikan.
- Isi formulir lengkap lalu Simpan: pindah ke daftar, pesan hijau muncul, siswa baru ada di baris atas.
- Nomor HP dikosongkan: formulir ditolak dan tidak ada data baru.
- Menekan refresh setelah menambah tidak membuat siswa ganda.
- Tanpa
@csrfmuncul 419, dan setelah dikembalikan formulir bekerja lagi. php artisan test --filter=TambahSiswaTest→ 6 test hijau.
Pertanyaan pemahaman
- Apa beda
create()danstore()? Kenapa menambah data membutuhkan dua method? - Apa fungsi
@csrf? Apa yang terjadi kalau dihapus? - Mengapa setelah menyimpan kita
redirect, bukan langsung menampilkan halaman daftar? - Apa bedanya
Siswa::create($request->all())denganSiswa::create($data)yang dipakai di sini? Mana yang lebih aman, dan kenapa?
Tantangan
Tambahkan aturan yang lebih ketat: 'no_hp' => 'required|digits_between:10,13' dan 'nama' => 'required|min:3'. Coba isi nomor HP dengan huruf. Apakah ditolak? Setelah itu pikirkan: apa yang pengguna lihat di layar saat ditolak? (Simpan pertanyaan itu untuk Bab 9.) Kembalikan aturan ke semula agar test tetap hijau.
Kesalahan umum
| Gejala | Penyebab & solusi |
|---|---|
419 Page Expired |
@csrf hilang dari formulir. |
MassAssignmentException |
Nama kolom di $fillable tidak cocok dengan yang dikirim. |
Route [siswa.store] not defined |
Route::resource belum terdaftar atau salah nama (Bab 4). |
| Data tidak masuk, tidak ada pesan apa pun | Validasi gagal diam-diam. Pada Bab 9 kamu tahu penyebab dan perbaikannya. |
Undefined variable $request |
Lupa menuliskan Request $request di tanda kurung store(...). |
| Pesan sukses tidak muncul | Nama kunci berbeda: with('success', ...) harus cocok dengan session('success') di tampilan. |
➡️ Lanjut ke Bab 7 — Update: Mengubah Data Siswa.