2012-03-23 2 views
1

수정하려는 PHP/MySQL 폴링이 있습니다.PHP/MySQL 투표 - IP 기반의 반복 투표 없음

투표를 한 경우 고유 한 쿠키를 설정하고 쿠키가 설정된 경우 동일한 설문 조사에서 두 번 투표하지 못하게합니다. 설정하면 결과 만 볼 수 있습니다.

내가 원하는 것은 IP가 데이터베이스에있는 경우 사용자가 두 번 이상 투표하지 못하도록 차단하는 것입니다. 세션이 더 좋을 수도 있지만 상황에 따라 불가능할 수도 있습니다.

필자는 IP를 수집하여 db에 저장했지만 데이터베이스에 있는지 여부를 설문 할 수있는 논리를 파악할 수 없습니다.

누군가 나를 올바른 방향으로 안내 할 수 있습니까?

쿠키 검색은 생성자 및 투표 방법에 있습니다. 쿠키는 투표 방법의 끝에서 설정됩니다.

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

    } 
    ?> 

그리고 여기에는 투표가 구현되는 방법은 다음과 같습니다 사용자가 IP 및 QID을하고 있는지에 대한 모든 로직이 생성자에서, 단순히 IP 테이블에 대해 쿼리를 수행하는 것처럼

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

답변

0

보이는 결과의 수는 0보다 큽니다. 그렇다면 생성자의 마지막 줄을 변경하십시오. isset ($ _ COOKIE [$ this-> md5] || count ($ res)> 0)? $ this-> poll (self :: VOTES) : $ this-> poll (self :: POLL);

+0

감사합니다. 나는 이것을 시도하고 나중에 다시보고 할 것이다. –

+0

그건 속임수 였어. 고마워. –