سیستم نظرسنجی و رای گیری (voting) در PHP

سیستم نظرسنجی و رای گیری (voting) در PHP

نظرسنجی در PHP – شاید به این فکر افتاده اید که در مورد یک موضوعی از کاربران رای گیری کنید .

با کمک این آموزش سیستم نظرسنجی و رای گیری جهت جمع آوری اطلاعات در مورد یک موضوع را یاد خواهیم گرفت .

در این آموزش از PHP , MySQL , javascript , Ajax استفاده می کنیم .

دموی سیستم نظرسنجی PHP


شرح پروژه

این سیستم از آیپی جهت جلوگیری از تقلب کاربران استفاده می کند .

شرح کارایی اسکریپت ها :

  1. index.php : صفحه ورود کاربر و ثبت رای آن
  2. functions.php : توابع کاربردی را شامل می شود ← شامل توابع ( دریافت آیپی کاربر ، دریافت تمامی آمار رای گیری
  3. db.php : توابع مورد نیاز جهت صحبت با MySQL
  4. api.php : زمانی با ajax درخواستی را ارسال می کنیم endpoint مان این اسکریپت می باشد
  5. func.php : توابع مورد نیاز با توجه به هر action که کاربر می خواهد انجام دهد مثل اکشن های * ثبت رای * آمار نظرسجی
  6. app.js : رفتاریات فعال در صفحه را با این اسکریپت انجام می دهیم همچنین مسئول اعتبار سنجی داده های ارسالی از سمت کلاینت و ارسال ajax می باشد .


1- اسکریپت index.php

<!DOCTYPE html>
<html lang="fa" dir="rtl">

<head>
    <meta charset="UTF-8">
    <title>Rapidcode.iR - سورس کد</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
    <link rel="stylesheet" href="static/css/main.css">
</head>

<body>


    <div class="container">
        <a class="text-center" id="introduce" href="https://rapidcode.ir" target="_blank">رپید کد • کتابخانه مجازی برنامه نویسان</a>


        <div class="statistics" dir="ltr">
            <h2 class="text-center bg-warning p-2">نتایج</h2>
            <div class="result-wrapper">
                <label for="">گوگل</label>
                <div class="progress progress-q1 mb-3">
                    <div class="progress-bar progress-bar-striped" role="progressbar" aria-valuemin="0" aria-valuemax="100">0</div>
                </div>
            </div>

            <div class="result-wrapper">
                <label for="">یوتیوب</label>
                <div class="progress progress-q2 mb-3">
                    <div class="progress-bar progress-bar-striped bg-success" role="progressbar" aria-valuemin="0" aria-valuemax="100">0</div>
                </div>
            </div>


            <div class="result-wrapper">
                <label for="">دوستان</label>
                <div class="progress progress-q3 mb-3">
                    <div class="progress-bar progress-bar-striped bg-info" role="progressbar" aria-valuemin="0" aria-valuemax="100">0</div>
                </div>
            </div>

            <div class="result-wrapper">
                <label for="">غیره</label>
                <div class="progress progress-q4 mb-3">
                    <div class="progress-bar progress-bar-striped bg-warning" role="progressbar" aria-valuemin="0" aria-valuemax="100">0</div>
                </div>
            </div>
        </div>

        <form id="vote-form">
            <h1 class="text-center">چگونه با وبسایت رپید کد آشنا شدید ؟</h1>

            <div class="vote-question-wrapper" dir="ltr">
                <table class="w-25 m-auto mt-5 table table-success">
                    <tbody>
                        <tr>
                            <td class="text-end"><label for="q1" class="me-2">گوگل</label></td>
                            <td> <input type="radio" class="form-check-input" name="inp-vote" id="q1" value="q1" checked><br></td>
                        </tr>
                        <tr>
                            <td class="text-end"><label for="q2" class="me-2">یوتیوب</label></td>
                            <td><input type="radio" class="form-check-input" name="inp-vote" id="q2" value="q2"><br></td>
                        </tr>

                        <tr>
                            <td class="text-end"><label for="q3" class="me-2">دوستان</label></td>
                            <td><input type="radio" class="form-check-input" name="inp-vote" id="q3" value="q3"><br></td>
                        </tr>

                        <tr>
                            <td class="text-end"><label for="q4" class="me-2">غیره</label></td>
                            <td><input type="radio" class="form-check-input" name="inp-vote" id="q4" value="q4"><br></td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <div class="text-center mt-3">
                <button type="button" id="submit_vote" class="btn btn-outline-success pe-4 ps-4 ">ثبت</button>
            </div>

        </form>


    </div>


    <script src="static/js/app.js"></script>
</body>

</html>


2- functions.php

<?php

require_once "db.php";


function rest_response($list, $need_die = false)
{
    $res = json_encode($list);
    return $need_die ? die($res) : $res;
}

function get_user_ip()
{
    $ip = null;

    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }

    return $ip;
}

function check_empty_list($list)
{
    $empty_list = [];
    foreach ($list as $elementKey => $elementValue) {
        if ($elementValue == "" || $elementValue === null) {
            $empty_list[$elementKey] = $elementValue;
        }
    }

    return $empty_list;
}

function getVoteResult()
{
    $row = selectRow("vote", [], null, "SELECT (SELECT COUNT(*) FROM `vote`) as total, (SELECT COUNT(*) FROM `vote` WHERE `voted`=\"q1\") as q1, (SELECT COUNT(*) FROM `vote` WHERE `voted`=\"q2\") as q2, (SELECT COUNT(*) FROM `vote` WHERE `voted`=\"q3\") as q3, (SELECT COUNT(*) FROM `vote` WHERE `voted`=\"q4\") as q4;");
    $row = $row[0] ?? [];

    return $row;
}


3- db.php

<?php
 
function startMysql()
{
    $GLOBALS['mysqli'] = new mysqli("localhost", "root", "", "vote_system");
    if ($GLOBALS['mysqli']->connect_error) {
        die("MYSQL ISSUE : " . $GLOBALS['mysqli']->connect_error);
    }
 
    $GLOBALS['mysqli']->set_charset("utf8");
    $GLOBALS['stmt'] = $GLOBALS['mysqli']->stmt_init();
}
 
function endMysql()
{
    $GLOBALS['stmt']->close();
    $GLOBALS['mysqli']->close();
}
 
function insertRow($data, $table, $interface = null, $where = ["keys" => "", "values" => []])
{
    startMysql();
 
    $keys = array_keys($data);
    $keysStr = join(",", $keys);
 
    $values = array_values($data);
 
    if ($interface == "update") {
        $keysStr = "";
        foreach ($data as $theKey => $theValue) {
            $keysStr .= "{$theKey}=?, ";
        }
 
        $keysStr = substr($keysStr, 0, strlen($keysStr) - 2);
 
        if (count($where['values'])) {
            $values = array_merge($values, $where['values']);
            $where['keys'] = " WHERE " . $where['keys'];
        }
 
        $query = "UPDATE `{$table}` SET {$keysStr}" . $where['keys'];
    } else if ($interface === null) {
 
        $valuesStrQuestion = str_repeat("? , ", count($values));
 
        if (1 < count($values)) {
            $valuesStrQuestion = substr($valuesStrQuestion, 0, strlen($valuesStrQuestion) - 3);
        }
 
        $query = "INSERT INTO `{$table}` ({$keysStr}) VALUES ({$valuesStrQuestion})";
    }
 
    $inserted_id = 0;
    $GLOBALS['stmt']->prepare($query);
    $GLOBALS['stmt']->bind_param(str_repeat("s", count($values)), ...$values);
 
    if ($GLOBALS['stmt']->execute()) {
        $inserted_id = $GLOBALS['stmt']->affected_rows;
 
        if ($interface === null) {
            $inserted_id = $GLOBALS['stmt']->insert_id;
        }
    }
 
    endMysql();
 
    return $inserted_id;
}
 
function selectRow($table, $data = [], $concat_query = "1=1" , $rawQuery = "")
{
    startMysql();
 
    $query = $rawQuery ? $rawQuery : "SELECT * FROM `{$table}` WHERE {$concat_query}";
    $rows = [];
 
    $GLOBALS['stmt']->prepare($query);
    if ($data) {
        $GLOBALS['stmt']->bind_param(str_repeat("s", count($data)), ...$data);
    }
 
    if ($GLOBALS['stmt']->execute() && $res = $GLOBALS['stmt']->get_result()) {
        if ($GLOBALS['stmt']->affected_rows || $res->num_rows) {
            while ($row = $res->fetch_assoc()) {
                $rows[] = $row;
            }
        }
    }
 
    endMysql();
 
    return $rows;
}
 
function updateRow($data, $table, $where = ["keys" => "", "values" => []])
{
    $affectefRows = insertRow($data, $table, "update", $where);
    return $affectefRows;
}
 
function isRowExists($table, $data, $concat_query)
{
    $rows = selectRow($table, $data, $concat_query);
 
    if (!$rows) return false;
    else {
        return $rows[0];
    }
}


4- api.php

<?php

require_once "../inc/functions.php";
require_once "func.php";

header("Content-Type: application/json");
header("Access-Control-Allow-Origin: *");

$response = [
    "status" => 0,
    "message" => "",
    "data" => "",
];

$action = @$_POST['action'];

$valid_actions = [
    "rest_action_submit_vote",
    "rest_action_result_vote",
];

if(!in_array($action , $valid_actions)){
    $response['message'] = "اکشن داده شده معتبر نیست ({$action})";
    rest_response($response , true);
}

call_user_func($action , $response);


5- func.php

<?php

function rest_action_submit_vote()
{
    $userEntry = [
        "ip" => get_user_ip(),
        "voted" => @$_POST['voted']
    ];

    $emptyList_userEntry = check_empty_list($userEntry);

    if ($emptyList_userEntry) {
        $emptyList_userEntry_keys = array_keys($emptyList_userEntry);
        $response['message'] = str_replace("x", join(",", $emptyList_userEntry_keys), "فیلد های x به درستی وارد نشده");
        rest_response($response, true);
    }

    $list_answers = [
        "q1",
        "q2",
        "q3",
        "q4",
    ];

    if (!in_array($userEntry['voted'], $list_answers)) {
        $response['message'] = "پاسخ داده شده نامعتبر می باشد";
        rest_response($response, true);
    }

    $rows = selectRow("vote", [$userEntry['ip']], "ip = ?");

    if ($rows) {
        $response['message'] = "از قبل در این نظرسنجی شرکت کرده اید";
        rest_response($response, true);
    } else {
        $vote_id = insertRow($userEntry, "vote");
        if ($vote_id) {
            $vote_result = getVoteResult();

            $response['status'] = 1;
            $response['message'] = "رای شما با موفقیت ثبت گردید";
            $response['data'] = $vote_result;
            rest_response($response, true);
        } else {
            $response['message'] = "مشکلی در ثبت رای پیش آمده";
            rest_response($response, true);
        }
    }
}

function rest_action_result_vote()
{
    $vote_result = getVoteResult();

    $response['status'] = 1;
    $response['message'] = "داده ها با موفقیت دریافت گردید";
    $response['data'] = $vote_result;

    rest_response($response, true);
}


6- app.js




document.addEventListener("DOMContentLoaded", function () {


    function markCheckedRadio() {
        const thisElement = this;
        Answer = thisElement.value;
    }

    function buildQueryByObject(obj) {
        var str = [];
        for (var p in obj)
            if (obj.hasOwnProperty(p)) {
                str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
            }
        return str.join("&");
    }

    function updateStatisticsAction(data) {
        const result = data;
        for (const key of Object.keys(data)) {
            const element = result[key];
            const dom = document.querySelector(`.progress-${key} .progress-bar`);

            if (dom === null) continue;


            const percent = Math.round((element / result["total"] * 100));
            const percentText = `${percent}%`;

            if (percent === 0) {
                continue;
            }

            dom.textContent = percentText;
            dom.style.width = percentText;
        }
    }

    function updateStatistics() {
        initXHR({
            "method": "POST",
            "query": "",
            "data": buildQueryByObject({
                "action": "rest_action_result_vote",
            }),
            "onload": function () {
                const response = this.response;
                if (response.status) {
                    updateStatisticsAction(response.data);
                } else {
                    alert(response.message);
                }
            },
            "onerror": function () {
                console.warn("XHR ERROR");
                alert("خطا");
            }
        });
    }

    function initXHR(config) {
        const xhr = new XMLHttpRequest();
        xhr.responseType = "json";

        xhr.open(config['method'], location.origin + "/" + "rest/api.php" + (config['query'] ?? ""));

        xhr.onload = config['onload'];
        xhr.onerror = config['onerror'];

        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

        xhr.send((config['data'] ?? ""));
    }

    function submitBtnHandler() {
        if (Answer === null) {
            alert("هیچ رای انتخاب نشده یکی را انتخاب کنید");
            return;
        }

        initXHR({
            "method": "POST",
            "query": "",
            "data": buildQueryByObject({
                "action": "rest_action_submit_vote",
                "voted": Answer,
            }),
            "onload": function () {
                const response = this.response;


                if (response.status) {
                    updateStatisticsAction(response.data);
                }

                alert(response.message);

            },
            "onerror": function () {
                console.warn("XHR ERROR");
                alert("خطا");
            }
        });

    }

    let Answer = null;

    const submitBtn = document.getElementById("submit_vote");

    let i = 0;
    for (let element of document.querySelectorAll("[name=inp-vote]")) {
        element.addEventListener("input", markCheckedRadio);
        i++;

        if (i === 1) {
            element.dispatchEvent(new Event("input"));
        }
    }

    updateStatistics();

    submitBtn.addEventListener("click", submitBtnHandler);

});


1- قبل از استفاده وارد پوشه to import و در دیتابیس وارد کنید .
2- وارد اسکریپت db.php و تابع startMysql شده و اطلاعات ورود به دیتابیس را مطابق با هاست خود تنظیم کنید .

دانلود سورس نظرسنجی در PHP

ارسال نظر

جهت استفاده از کد حتما از تگ pre استفاده نمایید .

contact us