Project PHP MySQL: Membuat Aplikasi Voting Sederhana (Lengkap Langkah-Langkah Code)
Aplikasi voting digital menjadi solusi efektif untuk berbagai kebutuhan seperti pemilihan OSIS, survei kepuasan pelanggan, atau polling cepat. Dalam tutorial ini, kita akan membuat Aplikasi Voting Sederhana menggunakan PHP dan MySQL yang memungkinkan pengguna untuk:
- Memberikan suara pada pilihan yang tersedia
- Menyimpan hasil voting ke database
- Menampilkan hasil voting secara real-time
Yang akan Anda pelajari:
✔ Koneksi PHP dengan MySQL
✔ Pembuatan form voting interaktif
✔ Penyimpanan data ke database
✔ Menampilkan hasil dalam bentuk tabel dan grafik
Langkah 1: Persiapan Project
Tools yang Dibutuhkan:
- XAMPP/WAMP/LAMP/Laragon (Local server)
- Text Editor (VS Code, Sublime Text, dll)
- Browser (Chrome, Firefox)
Struktur Folder:
📂 voting-app ├── 📂 assets │ ├── 📜 style.css │ └── 📜 script.js ├── 📂 includes │ ├── 📜 config.php │ └── 📜 functions.php ├── 📜 index.php ├── 📜 vote.php ├── 📜 results.php
Langkah 2: Membuat Database
- Buka phpMyAdmin di browser (
http://localhost/phpmyadmin
) - Buat database baru dengan nama
voting_db
- Buat tabel
pilihan
danhasil_voting
:
CREATE TABLE pilihan ( id INT(11) AUTO_INCREMENT PRIMARY KEY, nama_pilihan VARCHAR(100) NOT NULL, deskripsi TEXT ); CREATE TABLE hasil_voting ( id INT(11) AUTO_INCREMENT PRIMARY KEY, pilihan_id INT(11) NOT NULL, waktu_voting TIMESTAMP DEFAULT CURRENT_TIMESTAMP, ip_address VARCHAR(50) );
- Masukkan beberapa data contoh:
INSERT INTO pilihan (nama_pilihan, deskripsi) VALUES ('Kandidat A', 'Visi: Meningkatkan kualitas pendidikan'), ('Kandidat B', 'Visi: Memperbaiki fasilitas sekolah'), ('Kandidat C', 'Visi: Meningkatkan kegiatan ekstrakurikuler');
Langkah 3: Koneksi Database (config.php)
<?php
$host = "localhost";
$user = "root";
$pass = "";
$db = "voting_db";
$conn = new mysqli($host, $user, $pass, $db);
if ($conn->connect_error) {
die("Koneksi gagal: " . $conn->connect_error);
}
?>
Langkah 4: Halaman Utama (index.php)
<?php include 'includes/config.php'; ?> <!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Aplikasi Voting</title> <link rel="stylesheet" href="assets/style.css"> </head> <body> <div class="container"> <h1>SISTEM VOTING ONLINE</h1> <div class="pilihan-container"> <?php $sql = "SELECT * FROM pilihan"; $result = $conn->query($sql); if ($result->num_rows > 0) { while($row = $result->fetch_assoc()) { echo '<div class="pilihan-box">'; echo '<h3>'.$row["nama_pilihan"].'</h3>'; echo '<p>'.$row["deskripsi"].'</p>'; echo '<form action="vote.php" method="POST">'; echo '<input type="hidden" name="pilihan_id" value="'.$row["id"].'">'; echo '<button type="submit" class="btn-vote">VOTE</button>'; echo '</form>'; echo '</div>'; } } else { echo "<p>Tidak ada pilihan voting tersedia</p>"; } ?> </div> <a href="results.php" class="btn-results">Lihat Hasil</a> </div> </body> </html>
Langkah 5: Proses Voting (vote.php)
<?php
include 'includes/config.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$pilihan_id = $_POST['pilihan_id'];
$ip_address = $_SERVER['REMOTE_ADDR'];
// Cek apakah IP sudah pernah voting
$check_sql = "SELECT * FROM hasil_voting WHERE ip_address = '$ip_address'";
$check_result = $conn->query($check_sql);
if ($check_result->num_rows > 0) {
echo "<script>alert('Anda sudah melakukan voting sebelumnya!'); window.location.href='index.php';</script>";
} else {
// Simpan voting
$insert_sql = "INSERT INTO hasil_voting (pilihan_id, ip_address) VALUES ('$pilihan_id', '$ip_address')";
if ($conn->query($insert_sql)) {
echo "<script>alert('Terima kasih atas partisipasi Anda!'); window.location.href='results.php';</script>";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
}
}
?>
Langkah 6: Tampilan Hasil (results.php)
<?php include 'includes/config.php'; ?> <!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hasil Voting - Azroi</title> <link rel="stylesheet" href="assets/style.css"> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> </head> <body> <div class="container"> <h1>HASIL VOTING</h1> <div class="chart-container"> <canvas id="hasilChart"></canvas> </div> <div class="table-container"> <table> <tr> <th>No</th> <th>Kandidat</th> <th>Jumlah Suara</th> <th>Persentase</th> </tr> <?php $total_sql = "SELECT COUNT(*) as total FROM hasil_voting"; $total_result = $conn->query($total_sql); $total_row = $total_result->fetch_assoc(); $total_votes = $total_row['total']; $sql = "SELECT p.id, p.nama_pilihan, COUNT(h.id) as jumlah FROM pilihan p LEFT JOIN hasil_voting h ON p.id = h.pilihan_id GROUP BY p.id"; $result = $conn->query($sql); $no = 1; if ($result->num_rows > 0) { while($row = $result->fetch_assoc()) { $persentase = ($total_votes > 0) ? round(($row['jumlah'] / $total_votes) * 100, 2) : 0; echo '<tr>'; echo '<td>'.$no++.'</td>'; echo '<td>'.$row["nama_pilihan"].'</td>'; echo '<td>'.$row["jumlah"].'</td>'; echo '<td>'.$persentase.'%</td>'; echo '</tr>'; } } ?> <tr class="total-row"> <td colspan="2">TOTAL</td> <td><?php echo $total_votes; ?></td> <td>100%</td> </tr> </table> </div> <a href="index.php" class="btn-back">Kembali ke Voting</a> </div> <script> // Grafik Chart.js const ctx = document.getElementById('hasilChart').getContext('2d'); const chart = new Chart(ctx, { type: 'bar', data: { labels: [ <?php $sql = "SELECT p.nama_pilihan FROM pilihan p"; $result = $conn->query($sql); while($row = $result->fetch_assoc()) { echo "'".$row["nama_pilihan"]."',"; } ?> ], datasets: [{ label: 'Jumlah Suara', data: [ <?php $sql = "SELECT COUNT(h.id) as jumlah FROM pilihan p LEFT JOIN hasil_voting h ON p.id = h.pilihan_id GROUP BY p.id"; $result = $conn->query($sql); while($row = $result->fetch_assoc()) { echo $row["jumlah"].","; } ?> ], backgroundColor: [ 'rgba(255, 99, 132, 0.7)', 'rgba(54, 162, 235, 0.7)', 'rgba(255, 206, 86, 0.7)' ], borderWidth: 1 }] }, options: { responsive: true, scales: { y: { beginAtZero: true } } } }); </script> </body> </html>
Langkah 7: Styling CSS (assets/style.css)
* { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f5f5f5; color: #333; line-height: 1.6; } .container { max-width: 1000px; margin: 50px auto; padding: 20px; background: white; border-radius: 10px; box-shadow: 0 0 20px rgba(0,0,0,0.1); } h1 { text-align: center; margin-bottom: 30px; color: #2c3e50; } .pilihan-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 30px; } .pilihan-box { border: 1px solid #ddd; padding: 20px; border-radius: 8px; transition: transform 0.3s ease; } .pilihan-box:hover { transform: translateY(-5px); box-shadow: 0 5px 15px rgba(0,0,0,0.1); } .pilihan-box h3 { color: #3498db; margin-bottom: 10px; } .pilihan-box p { color: #7f8c8d; margin-bottom: 15px; } .btn-vote { background: #2ecc71; color: white; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; font-weight: bold; width: 100%; transition: background 0.3s ease; } .btn-vote:hover { background: #27ae60; } .btn-results, .btn-back { display: block; text-align: center; background: #3498db; color: white; padding: 10px; border-radius: 5px; text-decoration: none; margin-top: 20px; transition: background 0.3s ease; } .btn-results:hover, .btn-back:hover { background: #2980b9; } .table-container { margin: 30px 0; overflow-x: auto; } table { width: 100%; border-collapse: collapse; margin-bottom: 20px; } th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; } th { background-color: #3498db; color: white; } tr:hover { background-color: #f5f5f5; } .total-row { font-weight: bold; background-color: #f8f9fa; } .chart-container { margin: 40px 0; position: relative; height: 400px; } @media (max-width: 768px) { .container { margin: 20px; padding: 15px; } .pilihan-container { grid-template-columns: 1fr; } }
Langkah 8: Fitur Keamanan Tambahan
Tambahkan di functions.php
:
<?php
function sanitize_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
function validate_ip($ip) {
return filter_var($ip, FILTER_VALIDATE_IP);
}
?>
Lalu modifikasi vote.php
:
<?php
include 'includes/config.php';
include 'includes/functions.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$pilihan_id = sanitize_input($_POST['pilihan_id']);
$ip_address = validate_ip($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'unknown';
// ... kode sebelumnya ...
}
?>
Pengembangan Lanjutan
- Login Admin:
- Tambahkan tabel
admin
di database - Buat halaman login di
admin/login.php
- Fitur reset voting
- Tambahkan tabel
- Batas Waktu Voting:
- Ekspor Hasil ke Excel
Kesimpulan
Anda telah berhasil membuat:
✅ Sistem voting online dengan PHP MySQL
✅ Penyimpanan data ke database
✅ Tampilan hasil real-time dengan grafik
✅ Proteksi dasar terhadap duplikasi voting
Selamat mencoba! 🎉 Jangan ragu untuk mengembangkan aplikasi ini lebih lanjut sesuai kebutuhan Anda.