title: How can I implement a voting system on my site limiting votes to a single vote?
body: <p>I am trying to build a site with news links that can be voted, I have the following code:</p>
  
  <pre><code> case 'vote':
                  require_once('auth/auth.php');
                  if(Auth::isUserLoggedIn())
                  {
                      require_once('data/article.php');
                      require_once('includes/helpers.php');
  
                      $id = isset($_GET['param'])? $_GET['param'] : 0;
                      if($id &gt; 0)
                      {
                          $article = Article::getById($id);
                          $article-&gt;vote();
                          $article-&gt;calculateRanking();
                      }
                      if(!isset($_SESSION)) session_start();
                      redirectTo($_SESSION['action'], $_SESSION['param']);
                  }
                  else
                  {
                      Auth::redirectToLogin(); 
                  }
                  break;
  </code></pre>
  
  <p>The problem right now is how to check so the same user does not vote twice, here is the article file:</p>
  
  <pre><code>&lt;?php
  require_once($_SERVER['DOCUMENT_ROOT'].'/config.php'); 
  require_once(SITE_ROOT.'includes/exceptions.php'); 
  require_once(SITE_ROOT.'data/model.php');
  require_once(SITE_ROOT.'data/comment.php');
  
  class Article extends Model 
  {
      private $id;
      private $user_id;
      private $url;
      private $title;
      private $description;
      private $ranking;
      private $points;
  
      function __construct($title = ' ', $description = ' ', $url = ' ', $username = ' ', $created = ' ', $modified = '') {
  
          $this-&gt;setId(0);
          $this-&gt;setCreated($created);
          $this-&gt;setModified($modified);
          $this-&gt;setUsername($username);
          $this-&gt;setUrl($url);
          $this-&gt;setTitle($title);
          $this-&gt;setDescription($description);
          $this-&gt;setRanking(0.0);
          $this-&gt;setPoints(1); 
      }
  
      function getId(){
          return $this-&gt;id;
      }
  
      private function setId($value){
          $this-&gt;id = $value;
      }
  
      function getUsername(){
          return $this-&gt;username;
      }
  
      function setUsername($value){
          $this-&gt;username = $value;
      }
  
      function getUrl(){
          return $this-&gt;url;
      }
  
      function setUrl($value){
          $this-&gt;url = $value;
      }
  
      function getTitle()
      {
          return $this-&gt;title;
      }
  
      function setTitle($value) {
  
          $this-&gt;title = $value;
      }
  
      function getDescription() {
  
      return $this-&gt;description;
      }
  
      function setDescription($value)
      {
          $this-&gt;description = $value;
      }
  
      function getPoints()
      {
          return $this-&gt;points;
      }
  
      function setPoints($value) 
      {
          $this-&gt;points = $value;
      }
  
      function getRanking()
      {
          return $this-&gt;ranking;
      }
  
      function setRanking($value)
      {
          $this-&gt;ranking = $value;
      }
  
      function calculateRanking()
      {
          $created = $this-&gt;getCreated();
  
          $diff = $this-&gt;getTimeDifference($created, date('F d, Y h:i:s A'));
  
          $time = $diff['days'] * 24;
          $time += $diff['hours'];
          $time += ($diff['minutes'] / 60);
          $time += (($diff['seconds'] / 60)/60);
  
          $base = $time + 2;        
  
          $this-&gt;ranking = ($this-&gt;points - 1) / pow($base, 1.5);
  
          $this-&gt;save();
      }
  
      function vote()
      {
          $this-&gt;points++;
          $this-&gt;save();
      }
  
      function getUrlDomain()
      {
          /* We extract the domain from the URL
           * using the following regex pattern
           */
  
          $url = $this-&gt;getUrl();
          $matches = array(); 
          if(preg_match('/http:\/\/(.+?)\//', $url, $matches))
          {
              return $matches[1];
          }
          else
          {
              return $url;
          }
      }
  
      function getTimeDifference( $start, $end )
      {
          $uts['start']      =    strtotime( $start );
          $uts['end']        =    strtotime( $end );
          if( $uts['start']!==-1 &amp;&amp; $uts['end']!==-1 )
          {
              if( $uts['end'] &gt;= $uts['start'] )
              {
                  $diff    =    $uts['end'] - $uts['start'];
                  if( $days=intval((floor($diff/86400))) )
                      $diff = $diff % 86400;
                  if( $hours=intval((floor($diff/3600))) )
                      $diff = $diff % 3600;
                  if( $minutes=intval((floor($diff/60))) )
                      $diff = $diff % 60;
                  $diff    =    intval( $diff );
                  return( array('days'=&gt;$days, 'hours'=&gt;$hours, 'minutes'=&gt;$minutes, 'seconds'=&gt;$diff) );
              }
              else
              {
                  echo( "Ending date/time is earlier than the start date/time");
              }
          }
          else
          {
              echo( "Invalid date/time data detected");
          }
          return( false );
      }
  
  
  
      function getElapsedDateTime()
      {
          $db = null;
          $record = null;
  
          $record = Article::getById($this-&gt;id);
          $created = $record-&gt;getCreated();         
  
          $diff = $this-&gt;getTimeDifference($created, date('F d, Y h:i:s A'));
          //echo 'new date is '.date('F d, Y h:i:s A');
          //print_r($diff);
  
          if($diff['days'] &gt; 0 )
          {
              return sprintf("hace %d dias", $diff['days']);
          }
          else if($diff['hours'] &gt; 0 )
          {
              return sprintf("hace %d horas", $diff['hours']);
          }
          else if($diff['minutes'] &gt; 0 )
          {
              return sprintf("hace %d minutos", $diff['minutes']);
          }
          else
          {
              return sprintf("hace %d segundos", $diff['seconds']);
          }
      }
  
      function save() {
  
      /*
              Here we do either a create or
              update operation depending
              on the value of the id field.
              Zero means create, non-zero
              update
      */
  
          if(!get_magic_quotes_gpc())
          {
              $this-&gt;title = addslashes($this-&gt;title);
              $this-&gt;description = addslashes($this-&gt;description);
          }
  
          try
          {
              $db = parent::getConnection();
              if($this-&gt;id == 0 )
              {
                  $query = 'insert into articles (modified, username, url, title, description, points )';
                  $query .= " values ('$this-&gt;getModified()', '$this-&gt;username', '$this-&gt;url', '$this-&gt;title', '$this-&gt;description', $this-&gt;points)";
              }
              else if($this-&gt;id != 0)
              {
                  $query = "update articles set modified = NOW()".", username = '$this-&gt;username', url = '$this-&gt;url', title = '".$this-&gt;title."', description = '".$this-&gt;description."', points = $this-&gt;points, ranking = $this-&gt;ranking where id = $this-&gt;id";
              }
  
              $lastid = parent::execSql2($query);
  
              if($this-&gt;id == 0 )
                  $this-&gt;id = $lastid;
  
          }
          catch(Exception $e){
              throw $e;
          }
      }
  
  
      function delete()
      {
          try
          {
              $db = parent::getConnection();
              if($this-&gt;id != 0)
              {                ;
                  /*$comments = $this-&gt;getAllComments();
                  foreach($comments as $comment)
                  {
                      $comment-&gt;delete();
                  }*/
                  $this-&gt;deleteAllComments();
                  $query = "delete from articles where id = $this-&gt;id";
              }
              parent::execSql($query);
  
  
          }
          catch(Exception $e){
              throw $e;
          }
      }
  
      static function getAll($conditions = ' ')
      {
          /* Retrieve all the records from the
           * database according subject to
           * conditions
           */
  
          $db = null;
          $results = null;
          $records = array();
          $query = "select id, created, modified, username, url, title, description, points, ranking from articles $conditions";
          try
          {
              $db = parent::getConnection();
  
              $results = parent::execSql($query);
  
              while($row = $results-&gt;fetch_assoc())
              {
                  $r_id = $row['id'];
                  $r_created = $row['created'];
                  $r_modified = $row['modified'];
  
                  $r_title = $row['title'];
                  $r_description = $row['description'];
  
                  if(!get_magic_quotes_gpc())
                  {
                      $r_title = stripslashes($r_title);
                      $r_description = stripslashes($r_description);
                  }
  
                  $r_url = $row['url'];
                  $r_username = $row['username'];
                  $r_points = $row['points'];
                  $r_ranking = $row['ranking'];
  
                  $article = new Article($r_title, $r_description , $r_url, $r_username, $r_created, $r_modified);
                  $article-&gt;id = $r_id;
                  $article-&gt;points = $r_points;
                  $article-&gt;ranking = $r_ranking;
                  $records[] = $article;
              }
              parent::closeConnection($db);
          }
          catch(Exception $e)
          {
              throw $e;
          }
  
          return $records;
      }
  
      static function getById($id)
      {/*
       *  Return one record from the database by its id */
  
          $db = null;
          $record = null;
  
          try
          {
              $db = parent::getConnection();
              $query = "select id, username, created, modified, title, url, description, points, ranking from articles where id = $id";
              $results = parent::execSQL($query);
              if(!$results) {
                  throw new Exception ('Record not found', EX_RECORD_NOT_FOUND);
              }
  
              $row = $results-&gt;fetch_assoc();
              parent::closeConnection($db);
  
              if(!get_magic_quotes_gpc())
              {
                  $row['title'] = stripslashes($row['title']);
                  $row['description'] = stripslashes($row['description']);
              }
  
  
              $article = new Article($row['title'], $row['description'], $row['url'], $row['username'], $row['created'], $row['modified']);
              $article-&gt;id = $row['id'];
              $article-&gt;points = $row['points'];
              $article-&gt;ranking = $row['ranking']; 
              return $article;
  
          }
          catch (Exception $e){
              throw $e;
          }
      }
  
      static function getNumberOfComments($id)
      {/*
       *  Return one record from the database by its id */
  
          $db = null;
          $record = null;
  
          try
          {
              $db = parent::getConnection();
              $query = "select count(*) as 'total' from comments where article_id = $id";
              $results = parent::execSQL($query);
              if(!$results) {
                  throw new Exception ('Comments Count Query Query Failed', EX_QUERY_FAILED);
              }
  
              $row = $results-&gt;fetch_assoc();
              $total = $row['total'];
              parent::closeConnection($db);    
  
              return $total;
  
  
          }
          catch (Exception $e){
              throw $e;
          }
      }
  
      function deleteAllComments()
      {/*
       *  Return one record from the database by its id */
  
          $db = null;
          try
          {
              $db = parent::getConnection();
              $query = "delete from comments where article_id = $this-&gt;id";
              $results = parent::execSQL($query);
              if(!$results) {
                  throw new Exception ('Deletion Query Failed', EX_QUERY_FAILED);
              }
              parent::closeConnection($db);
          }
          catch (Exception $e){
              throw $e;
          }
      }
  
  
      function getAllComments($conditions = ' ')
      {
          /* Retrieve all the records from the
           * database according subject to
           * conditions
           */
          $conditions = "where article_id = $this-&gt;id";
          $comments = Comment::getAll($conditions);
          return $comments; 
      }
  
  
      static function getTestData($url)
      {
          $page = file_get_contents($url);
  
  
  
  
      }
  
  }
  ?&gt;
  </code></pre>
  
  <p>Any suggestion or comment is appreciated, Thanks.</p>