Опрос PHP / MySQL - нет повторного голосования по IP - PullRequest
1 голос
/ 23 марта 2012

У меня есть опрос php / mysql, который я пытаюсь изменить.

Он устанавливает уникальный файл cookie, если вы проголосовали, и блокирует вас от голосования дважды в одном опросе, если файл cookie установлен. Если он установлен, то вы можете видеть только результаты.

Что я хотел бы сделать, так это запретить пользователю голосовать более одного раза, если его IP-адрес также есть в базе данных (я знаю, что сеансы будут лучше, но в моей ситуации это невозможно)

Мне удалось получить IP-адрес и сохранить его в БД, но я не могу понять логику, чтобы сообщить опросу, находится ли он в базе данных или нет.

Может ли кто-нибудь указать мне правильное направление?

Обнаружение cookie в методах конструктора и голосования. Файл cookie устанавливается в конце метода голосования.

    <?php
    # don't display errors
    ini_set('display_errors',0);
    error_reporting(E_ALL|E_STRICT); 

    class webPoll {

        # makes some things more readable later
        const POLL = true;
        const VOTES = false;

        # number of pixels for 1% on display bars
        public $scale = 2;
        public $question = '';
        public $answers = array();

        private $header = '<form class="webPoll" method="post" action="%src%">
                           <input type="hidden" name="QID" value="%qid%"/>
                           <h4>%question%</h4>
                           <fieldset><ul>';
        private $center = '';
        private $footer = "\n</ul></fieldset>%button%\n%totalvotes%\n</form>\n";
        private $button = '<p class="buttons"><button type="submit" class="vote">Vote!</button></p>';
        private $totalvotes = '';
        private $md5 = '';
        private $id = '';

        /**
         * ---
         * Takes an array containing the question and list of answers as an
         * argument. Creates the HTML for either the poll or the results depending
         * on if the user has already voted
         */
        public function __construct($params) {
            $this->id = array_shift($params);
            $this->question = array_shift($params);
            $this->answers = $params;
            $this->md5 = md5($this->id);
            $this->header = str_replace('%src%', $_SERVER['SCRIPT_NAME'], $this->header);
            $this->header = str_replace('%qid%', $this->md5, $this->header);
            $this->header = str_replace('%question%', $this->question, $this->header);

            # seperate cookie for each individual poll (has the user voted yet?)
            # if cookie is set then show results(VOTES), if not then let user vote(POLL)
            isset($_COOKIE[$this->md5]) ? $this->poll(self::VOTES) : $this->poll(self::POLL); 
        }
        private function poll($show_poll) {
            $replace_btn = $show_poll ? $this->button : '';
            $get_results = webPoll::getData($this->md5);
            $total_votes = array_sum($get_results);
            $replace_votes = $show_poll ? $this->totalvotes : '<small>Total Votes: '.$total_votes.'</small>';

            $this->footer = str_replace('%button%', $replace_btn, $this->footer);
            $this->footer = str_replace('%totalvotes%', $replace_votes, $this->footer);

            # static function doesn't have access to instance variable
            if(!$show_poll) {
                $results = webPoll::getData($this->md5);
                $votes = array_sum($results);
            }

            for( $x=0; $x<count($this->answers); $x++ ) {
                $this->center .= $show_poll ? $this->pollLine($x) : $this->voteLine($this->answers[$x],$results[$x],$votes);
            }
            echo $this->header, $this->center, $this->footer;
        }
        private function pollLine($x) {
            isset($this->answers[$x+1]) ? $class = 'bordered' : $class = '';
            return "
            <li class='$class'>
                    <label class='poll_active'>
                    <input type='radio' name='AID' value='$x' />
                        {$this->answers[$x]}
                    </label>
            </li>
        ";
        }
        private function voteLine($answer,$result,$votes) {
            $result = isset($result) ? $result : 0;
            $percent = round(($result/$votes)*100);
            $width = $percent * $this->scale;
            return "
            <li>
                    <div class='result' style='width:{$width}px;'>&nbsp;</div>{$percent}%
                    <label class='poll_results'>
                        $answer
                    </label>
            </li>
        ";
        }
        /**
         * processes incoming votes. votes are identified in the database by a combination
         * of the question's MD5 hash, and the answer # ( an int 0 or greater ).
         */
        static function vote() {

            if(!isset($_POST['QID']) || !isset($_POST['AID']) || isset($_COOKIE[$_POST['QID']])) {
                # leave vote method if any of the above are true
                return;
            }

            $dbh = new PDO('mysql:host=????;dbname=????', '????', '');
            $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

            try {
                # add vote info to 'tally' table
                $sth = $dbh->prepare("INSERT INTO tally (QID,AID,votes,created_at) values (?, ?, 1, NOW())");
                $ex = array($_POST['QID'],$_POST['AID']);
                $sth->execute($ex);
                # add ip info to 'ips' table
                $sth2 = $dbh->prepare("INSERT INTO ips (ips,QID,AID) values (?,?,?)");
                $ex2 = array($_SERVER['REMOTE_ADDR'],$_POST['QID'],$_POST['AID']);
                $sth2->execute($ex2);
            }
            catch(PDOException $e) {
                # 23000 error code means the key already exists, so UPDATE! 
                if($e->getCode() == 23000) {
                    try {
                        # update number of votes for answers in 'tally' table
                        $sth = $dbh->prepare("UPDATE tally SET votes = votes+1 WHERE QID=? AND AID=?");
                        $sth->execute(array($_POST['QID'],$_POST['AID']));
                        # add ip info to 'ips' table
                        $sth2 = $dbh->prepare("INSERT INTO ips (ips,QID,AID) values (?,?,?)");
                        $ex2 = array($_SERVER['REMOTE_ADDR'],$_POST['QID'],$_POST['AID']);
                        $sth2->execute($ex2);
                    }
                    catch(PDOException $e) {
                        webPoll::db_error($e->getMessage());
                    }
                }
                else {
                    webPoll::db_error($e->getMessage());
                }
            }

            # entry in $_COOKIE to signify the user has voted, if he has
            if($sth->rowCount() == 1) {
                setcookie($_POST['QID'], 1, time()+60*60*24*365, '/', '', FALSE, TRUE);
                $_COOKIE[$_POST['QID']] = 1;
            }
        }
        static function getData($question_id) {
            try {
                $dbh = new PDO('mysql:host=????;dbname=????', '????', '');
                $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

                $STH = $dbh->prepare('SELECT AID, votes FROM tally WHERE QID = ?');
                $STH->execute(array($question_id));
            }
            catch(PDOException $e) {  
                # Error getting data, just send empty data set
                return array(0); 
            }

            while($row = $STH->fetch()) {
                $results[$row['AID']] = $row['votes'];   
            }

            return $results;
        }
        /*
         * You can do something with the error message if you like. Email yourself
         * so you know something happened, or make an entry in a log
         */
        static function db_error($error) {   
            echo "A database error has occurred. $error";
            exit;
        } 

    }
    ?>

А вот как осуществляется опрос:

    <?php
        ini_set('display_errors',1);
        error_reporting(E_ALL|E_STRICT);

        include('webPoll-hiddenMD5.class.php');
        webPoll::vote();    
    ?>
    <html>
    <head>
        <title>Poll Test</title>
        <link rel="stylesheet" href="poll.css" type="text/css" />
        <!--[if IE]>
        <style> body { behavior: url("res/hover.htc"); } </style>
        <![endif]-->
    </head>
    <body>
    <?php

        $a1 = new webPoll(array(
                'March 16, 2012 What subjects would you like to learn more about?',            
                'What subjects would you like to learn more about?',
                'HTML & CSS',
                'Javascript',
                'JS Frameworks (Jquery, etc)',
                'Ruby/Ruby on Rails',
                'PHP',
                'mySQL'));

    ?>
    </body>
    </html>

1 Ответ

0 голосов
/ 23 марта 2012

Похоже, что вся ваша логика находится в конструкторе, просто выполните запрос к таблице ip для пользователей ip и qid и посмотрите, будет ли количество результатов больше 0. Если это так, просто измените последнюю строкуisset конструктора ($ _ COOKIE [$ this-> md5] || count ($ res)> 0)?$ this-> poll (self :: VOTES): $ this-> poll (self :: POLL);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...