Project PHP MySQL: Membuat Aplikasi Voting

Project PHP MySQL: Membuat Aplikasi Voting

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

  1. Buka phpMyAdmin di browser (http://localhost/phpmyadmin)
  2. Buat database baru dengan nama voting_db
  3. Buat tabel pilihan dan hasil_voting:
sql
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)
);
  1. Masukkan beberapa data contoh:
sql
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
<?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
<?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
<?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
<?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)

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
<?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
<?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

  1. Login Admin:
    • Tambahkan tabel admin di database
    • Buat halaman login di admin/login.php
    • Fitur reset voting
  2. Batas Waktu Voting:
  3. 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.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *