سیستم نظرسنجی و رای گیری (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 استفاده نمایید .

لیست نظرات

  1. محمود رنجبر نورآبادی
    محمود رنجبر نورآبادی

    سلام استاد باقری عزیز من میخوام سوالی ازتون بپرسم عکس هم توش هست میشه ایمیلتون رو برام بفرستید یا در جواب همین پیام قرار بدید با تشکر از شما

    28 آذر 1401 | 07:20:17
  • حسین باقری
    حسین باقری

    شماره واتساپ می تونید در ارتباط باشید فقط بین ساعت 9 الی 17 پاسخ گو هستم .

    28 آذر 1401 | 11:24:34
contact us