Tutorial Vibe Coding: Membuat Aplikasi CRUD PHP MySQLi Cepat dan Aman
Poin Kunci Artikel Ini:
- File koneksi database terisolasi dari logika tampilan.
- Form HTML menggunakan atribut validasi HTML5.
- Fitur hapus data menyertakan dialog konfirmasi.
Konsep CRUD dan Transformasi Vibe Coding
Membuat aplikasi CRUD (Create, Read, Update, Delete) merupakan pondasi dasar pengembangan web. Manajemen stok, e-commerce, hingga portal berita beroperasi dengan empat fungsi dasar ini. Bagi pemula, penulisan kode CRUD manual sering repetitif karena akumulasi boilerplate code.
Proses konvensional menuntut penulisan query SQL manual, pembuatan form input HTML, penanganan HTTP request, validasi server-side, hingga penyusunan tabel responsif. Melalui CRUD vibe coding, paradigma bergeser. Pengembang mengarahkan model AI untuk memproduksi struktur kode aplikasi CRUD AI berbasis PHP Native dan MySQLi secara cepat.
Vibe coding bukan menyerahkan kontrol penuh ke AI tanpa pengawasan. Pengembang bertindak sebagai arsitek sistem dan code reviewer, sedangkan AI bertindak sebagai eksekutor pengetikan kode. Pendekatan ini memangkas durasi pengembangan tanpa mengorbankan kualitas arsitektur maupun keamanan dasar aplikasi.
Perancangan Skema Database Manajemen Produk
Perancangan skema database presisi wajib dilakukan sebelum mengeksekusi prompt. AI membutuhkan atribut data terdefinisi spesifik agar tidak menghasilkan struktur tabel keliru atau eror relasi.
Studi kasus menggunakan sistem manajemen produk. Tabel products dirancang dengan struktur kolom berikut:
id: Identifier unik (Primary Key, Auto Increment, INT)name: Nama produk (VARCHAR 150, NOT NULL)sku: Kode stok unik (VARCHAR 50, UNIQUE, NOT NULL)price: Harga barang (DECIMAL 10,2, NOT NULL)stock: Jumlah stok barang (INT, DEFAULT 0, NOT NULL)created_at: Waktu pencatatan data (TIMESTAMP, DEFAULT CURRENT_TIMESTAMP)
Sintaks SQL untuk inisialisasi tabel:
CREATE TABLE `products` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(150) NOT NULL, `sku` VARCHAR(50) UNIQUE NOT NULL, `price` DECIMAL(10,2) NOT NULL, `stock` INT DEFAULT 0 NOT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;Formulasi Prompt Backend PHP dan MySQLi
Efektivitas CRUD vibe coding bergantung pada detail instruksi prompt. Instruksi teknis spesifik meminimalisir kesalahan sintaks dan celah keamanan. Berikut urutan prompt terstruktur untuk modul CRUD:
Langkah 1: Setup Koneksi Database (db.php)
Prompt koneksi database:
"Buatkan file PHP bernama db.php untuk menghubungkan aplikasi ke database MySQL bernama toko_db. Gunakan ekstensi MySQLi dengan pendekatan prosedural. Host: localhost, user: root, pass: empty. Sertakan penanganan eror koneksi menggunakan mysqli_connect_error() dan hentikan eksekusi jika koneksi gagal."
Langkah 2: Tampilan Data Utama (index.php)
Prompt halaman utama pembacaan data:
"Buatkan file index.php yang meng-include db.php. Tampilkan seluruh data dari tabel products dalam tabel HTML Bootstrap 5 CDN. Kolom tabel: No, Nama Produk, SKU, Harga (format Rupiah via number_format), Stok, dan Aksi. Kolom Aksi berisi tombol Edit dan Hapus. Tambahkan tombol 'Tambah Produk Baru' di atas tabel. Amankan output variabel HTML menggunakan htmlspecialchars()."
Langkah 3: Form Tambah dan Update Data (create.php dan edit.php)
Prompt modul pemrosesan data:
"Buatkan file create.php dan edit.php beserta script penanganannya. Ketentuan: 1) Styling form menggunakan Bootstrap 5. 2) Gunakan Prepared Statements (mysqli_prepare) untuk proses INSERT dan UPDATE. 3) Validasi server-side: input tidak boleh kosong, stok tidak boleh negatif. 4) Setelah sukses eksekusi, redirect ke index.php."
Langkah 4: Penghapusan Data Secure (delete.php)
Prompt fitur hapus data:
"Buatkan file delete.php yang menerima parameter id melalui method GET. Gunakan Prepared Statement untuk menghapus data berdasarkan id. Pada index.php, tambahkan konfirmasi JavaScript (onclick confirm) pada tombol hapus sebelum mengarah ke delete.php."
Implementasi Kode PHP Native dan MySQLi Procedural
Berikut implementasi kode lengkap hasil generasi prompt yang telah terverifikasi:
1. File Koneksi: db.php
<?php $host = "localhost"; $user = "root"; $pass = ""; $db = "toko_db"; $conn = mysqli_connect($host, $user, $pass, $db); if (!$conn) { die("Koneksi database gagal: " . mysqli_connect_error()); } ?>2. File Halaman Utama: index.php
<?php require_once 'db.php'; $query = "SELECT * FROM products ORDER BY id DESC"; $result = mysqli_query($conn, $query); ?> <!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <title>Manajemen Produk</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body class="container py-4"> <h2 class="mb-4">Daftar Produk</h2> <a href="create.php" class="btn btn-primary mb-3">Tambah Produk Baru</a> <table class="table table-bordered table-striped"> <thead class="table-dark"> <tr> <th>No</th> <th>Nama Produk</th> <th>SKU</th> <th>Harga</th> <th>Stok</th> <th>Aksi</th> </tr> </thead> <tbody> <?php $no = 1; while ($row = mysqli_fetch_assoc($result)) : ?> <tr> <td><?= $no++; ?></td> <td><?= htmlspecialchars($row['name'], ENT_QUOTES, 'UTF-8'); ?></td> <td><?= htmlspecialchars($row['sku'], ENT_QUOTES, 'UTF-8'); ?></td> <td>Rp <?= number_format($row['price'], 0, ',', '.'); ?></td> <td><?= (int)$row['stock']; ?></td> <td> <a href="edit.php?id=<?= $row['id']; ?>" class="btn btn-warning btn-sm">Edit</a> <a href="delete.php?id=<?= $row['id']; ?>" class="btn btn-danger btn-sm" onclick="return confirm('Yakin ingin menghapus data ini?')">Hapus</a> </td> </tr> <?php endwhile; ?> </tbody> </table> </body> </html>3. File Form Tambah Data: create.php
<?php require_once 'db.php'; $error = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $name = trim($_POST['name']); $sku = trim($_POST['sku']); $price = $_POST['price']; $stock = $_POST['stock']; if (empty($name) || empty($sku) || $price === '' || $stock === '') { $error = "Semua field harus diisi!"; } elseif ($stock < 0 || $price < 0) { $error = "Harga dan stok tidak boleh negatif!"; } else { $stmt = mysqli_prepare($conn, "INSERT INTO products (name, sku, price, stock) VALUES (?, ?, ?, ?)"); mysqli_stmt_bind_param($stmt, "ssdi", $name, $sku, $price, $stock); if (mysqli_stmt_execute($stmt)) { header("Location: index.php"); exit; } else { $error = "Gagal menyimpan data: SKU mungkin sudah ada."; } mysqli_stmt_close($stmt); } } ?> <!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <title>Tambah Produk</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body class="container py-4"> <h2>Tambah Produk Baru</h2> <?php if ($error): ?> <div class="alert alert-danger"><?= $error; ?></div> <?php endif; ?> <form method="POST" class="w-50"> <div class="mb-3"> <label class="form-label">Nama Produk</label> <input type="text" name="name" class="form-control" required> </div> <div class="mb-3"> <label class="form-label">SKU</label> <input type="text" name="sku" class="form-control" required> </div> <div class="mb-3"> <label class="form-label">Harga</label> <input type="number" step="0.01" name="price" class="form-control" required> </div> <div class="mb-3"> <label class="form-label">Stok</label> <input type="number" name="stock" class="form-control" required> </div> <button type="submit" class="btn btn-success">Simpan</button> <a href="index.php" class="btn btn-secondary">Batal</a> </form> </body> </html>4. File Form Edit Data: edit.php
<?php require_once 'db.php'; $id = $_GET['id'] ?? null; if (!$id) { header("Location: index.php"); exit; } $stmt = mysqli_prepare($conn, "SELECT * FROM products WHERE id = ?"); mysqli_stmt_bind_param($stmt, "i", $id); mysqli_stmt_execute($stmt); $product = mysqli_fetch_assoc(mysqli_stmt_get_result($stmt)); mysqli_stmt_close($stmt); if (!$product) { header("Location: index.php"); exit; } $error = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $name = trim($_POST['name']); $sku = trim($_POST['sku']); $price = $_POST['price']; $stock = $_POST['stock']; if (empty($name) || empty($sku) || $price === '' || $stock === '') { $error = "Semua field harus diisi!"; } else { $updateStmt = mysqli_prepare($conn, "UPDATE products SET name=?, sku=?, price=?, stock=? WHERE id=?"); mysqli_stmt_bind_param($updateStmt, "ssdii", $name, $sku, $price, $stock, $id); if (mysqli_stmt_execute($updateStmt)) { header("Location: index.php"); exit; } else { $error = "Gagal memperbarui data."; } mysqli_stmt_close($updateStmt); } } ?> <!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <title>Edit Produk</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body class="container py-4"> <h2>Edit Produk</h2> <?php if ($error): ?> <div class="alert alert-danger"><?= $error; ?></div> <?php endif; ?> <form method="POST" class="w-50"> <div class="mb-3"> <label class="form-label">Nama Produk</label> <input type="text" name="name" class="form-control" value="<?= htmlspecialchars($product['name']); ?>" required> </div> <div class="mb-3"> <label class="form-label">SKU</label> <input type="text" name="sku" class="form-control" value="<?= htmlspecialchars($product['sku']); ?>" required> </div> <div class="mb-3"> <label class="form-label">Harga</label> <input type="number" step="0.01" name="price" class="form-control" value="<?= $product['price']; ?>" required> </div> <div class="mb-3"> <label class="form-label">Stok</label> <input type="number" name="stock" class="form-control" value="<?= $product['stock']; ?>" required> </div> <button type="submit" class="btn btn-primary">Update</button> <a href="index.php" class="btn btn-secondary">Batal</a> </form> </body> </html>5. File Eksekusi Hapus Data: delete.php
<?php require_once 'db.php'; $id = $_GET['id'] ?? null; if ($id) { $stmt = mysqli_prepare($conn, "DELETE FROM products WHERE id = ?"); mysqli_stmt_bind_param($stmt, "i", $id); mysqli_stmt_execute($stmt); mysqli_stmt_close($stmt); } header("Location: index.php"); exit; ?>Prosedur Pengujian Fitur
Pengujian aplikasi hasil generasi AI dilakukan melalui empat skenario:
1. Pengujian Tambah Data (Create)
- Input Valid: Masukkan nama "Kopi Arabika", SKU "KOP-001", harga "45000", stok "20". Data tersimpan dan tampil di
index.php. - Input Invalid: Kosongkan kolom input atau masukkan angka negatif. Sistem menolak eksekusi dan menampilkan pesan peringatan.
- Handling Duplikat: Masukkan SKU terdaftar. Sistem menanggulangi eror duplikasi tanpa memunculkan fatal error.
2. Pengujian Tampilan Data (Read)
Buka index.php. Verifikasi data tampil berurutan berdasarkan ID terbaru. Format harga otomatis berubah ke format Rupiah (contoh: Rp 45.000).
3. Pengujian Perubahan Data (Update)
Klik tombol 'Edit'. Pastikan form edit.php terisi otomatis dengan data produk terkait. Ubah nilai stok atau harga lalu simpan. Verifikasi perubahan terefleksi di halaman utama.
4. Pengujian Penghapusan Data (Delete)
Klik tombol 'Hapus'. Dialog konfirmasi JavaScript muncul. Tombol 'Cancel' membatalkan proses. Tombol 'OK' mengeksekusi delete.php dan mengarahkan kembali ke index.php.
Analisis Keamanan: Prepared Statement dan Anti-XSS
Kode generasi AI wajib diaudit terhadap dua celah keamanan utama aplikasi web PHP.
1. Pencegahan SQL Injection
SQL Injection terjadi saat input pengguna digabungkan langsung ke query SQL. Prepared Statements memisahkan struktur query dan data input. Karakter berbahaya diisolasi sebagai nilai string murni.
$stmt = mysqli_prepare($conn, "DELETE FROM products WHERE id = ?"); mysqli_stmt_bind_param($stmt, "i", $id); mysqli_stmt_execute($stmt);2. Pencegahan Cross-Site Scripting (XSS)
XSS terjadi saat skrip HTML/JavaScript dari input dieksekusi browser. Fungsi htmlspecialchars() mengubah karakter khusus seperti < dan > menjadi HTML entities.
echo htmlspecialchars($row['name'], ENT_QUOTES, 'UTF-8');Checklist Kelayakan Operasional Modul
Pastikan seluruh poin checklist terpenuhi sebelum penyerahan modul:
- File koneksi database terisolasi dari logika tampilan.
- Form HTML menggunakan atribut validasi HTML5.
- Operasi INSERT, UPDATE, dan DELETE mengimplementasikan
mysqli_prepare. - Variabel keluaran HTML dibungkus
htmlspecialchars(). - Fitur hapus data menyertakan dialog konfirmasi.
- Eror SQL tidak menampilkan struktur sensitif ke publik.
Kesimpulan
Penerapan CRUD vibe coding membuktikan pembuatan modul backend PHP Native dan MySQLi dapat diselesaikan cepat dan presisi. Pengembang berfokus pada kualitas prompt, arsitektur data, serta audit keamanan.
Modul ini masih terbuka tanpa proteksi hak akses. Pembahasan berikutnya akan mencakup implementasi Autentikasi User (Login & Register) serta Manajemen Session PHP.



๐ฌ Komentar (0)
Tulis Komentar