2015-12-09 9 views
0

Я положительно теряю рассудок по этой проблеме. Я попытался сделать несколько сообщений об этом, но решил собрать все в этом финале, чтобы надеяться, как-то его решить.Удаление доступа для голосования по конкретному объекту в зависимости от IP-адреса, сохраненного в базе данных

Я создаю сайт, на котором пользователи могут голосовать по вопросам из базы данных. Там нет логина и поэтому, чтобы каждый мог голосовать только один раз за вопрос, я использую их IP вместе с идентификатором вопроса.

Первый я получаю ID и IP-адрес и сохранить как, убедившись, что они являются целыми числами:

if(isset($_GET['id'])) 
      { 

      //Get IP address 

      //Test if it is a shared client 
      if (!empty($_SERVER['HTTP_CLIENT_IP'])){ 
      $ip=$_SERVER['HTTP_CLIENT_IP']; 

      //Is it a proxy address 
      }elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){ 
      $ip=$_SERVER['HTTP_X_FORWARDED_FOR']; 
      }else{ 
      $ip=$_SERVER['REMOTE_ADDR']; 
      } 

      //Save id and IP address as variables 
      $id = $_GET['id']; 
      $ip_long = ip2long($ip); 

возникают Мои проблемы:

я затем проверить, чтобы увидеть, если пользователь уже имеет голоса, используя две переменные. Здесь я ожидаю, что проблема возникнет. Я получаю сообщение «» Уведомление: попытка получить свойство не-объекта 'из строки 116, которая является: $ row_cnt = $ result-> num_rows;.
Кроме того, var_dump ($ result); возвращает bool (false) и var_dump ($ row_cnt);Null. Добавляя кавычки вокруг двух переменных в запросе, $ ip_long и $ id исправляют проблему в то время как localhost, но не на моем сервере.
Местный var_dump ($ result); с кавычками вокруг переменных возвращает следующее: объект (mysqli_result) # 2 (5) {["current_field"] => int (0) ["field_count"] => int (1) ["lengths"] => NULL [ "num_rows"] => Int (1) [ "тип"] => Int (0)}

Я хотел бы добавить 1 к QuestionVotes для конкретного вопроса, а затем удалить опцию голосования по этому же вопросу для конкретного IP-адреса.

У меня нет подсказки, почему это не работает, и я буду благодарен за любую помощь или предложения!

//Save id and IP address as variables 
      $id = $_GET['id']; 
      $ip_long = ip2long($ip); 

      ///Check to see if user already voted 
      $stmt = $conn->prepare("SELECT * FROM User_Votes where UserID = ? and QuestionID = ?"); 
      mysqli_stmt_bind_param($stmt, 'ss', $ip_long, $id); 
      $stmt->execute(); 
      $result = $stmt->get_result(); 
      if($result->num_rows){ 
       //The user has already voted 
       echo "Already voted"; 
      }else{ 
       //Add IP Address and ID to the User_Votes table 
       $stmt = $conn->prepare("INSERT INTO User_Votes (UserID, QuestionID) VALUES (?, ?)"); 
       mysqli_stmt_bind_param($stmt, 'ss', $ip_long, $id); 
       $stmt->execute(); 
       $stmt = $conn->prepare("UPDATE Question SET QuestionVotes = QuestionVotes + 1 where QuestionID = ?"); 
       mysqli_stmt_bind_param($stmt, 's', $id); 
       $stmt->execute(); 
      } 

     } 

И, наконец, вот код, я использую для создания HTML ящиков, содержащих информацию вопроса базы данных, добавить кнопку голосования, который отображает текущие голоса и добавить, что используется в качестве QuestionID, к URL-адресу:

// Build 4 question boxes from database Question table, including voting button 
     $stmt = $conn->prepare("SELECT * FROM question ORDER BY QuestionVotes DESC LIMIT 4"); 
     $stmt->execute(); 

     $result = $stmt->get_result(); 
     if ($result->num_rows > 0) { 
      // output data of each row 
      while($row = $result->fetch_assoc()) { 
       //$row["QuestionID"] to add id to url 
       echo "<div class=\"col-md-3\"><h2>". $row["QuestionHeader"]. "</h2><p>". $row["QuestionText"]. "</p><p><a href=\"index.php?id=". $row["QuestionID"]. "\" class=\"btn btn-success\"> " . $row["QuestionVotes"] . "</a></p></div>"; 

      } 
     } 
     else 
     { 
     echo "0 results"; 
     } 

Мои таблицы следующим образом:
Вопрос: QuestionID (int11) (рк), QuestionHeader (VARCHAR (20)), QuestionText (текст), QuestionVot эс (интермедиат (5))
User_Votes: Идентификатор_пользователя (без знака, INT (39)), QuestionID (интермедиат (11))

Спасибо, что нашли время для чтения этого длинного поста. Скажите мне, нет ли какой-либо информации или что-то в этом роде. Опять же, любая помощь или предложение были бы очень благодарны!

+0

** Предупреждение о вводе SQL ** Никогда не используйте незащищенные данные, поступающие из браузера (как в '$ id = $ _GET ['id'];' затем следует запрос $ conn-> ("SELECT ...QuestionID = $ id ");'). Если я отправлю '1; DELETE * FROM question' в качестве значения для' id', вы не будете счастливы. – jcaron

+0

Ваш запрос возвращает 'false', что означает ошибку. значение '$ result' перед использованием. Если' false', запишите ошибку ('$ conn-> error'). – jcaron

+0

А, да, я знаю, что мой код уязвим для SQL-инъекции, но это не будет исправлено с помощью подготовленных операторов? И var_dump в $ result возвращает «bool (false)». Но я очень к этому не знаком, поэтому я не совсем уверен, где вы хотите, чтобы я использовал «($ conn-> error)»? вы направить меня? Кроме того, большое спасибо за ваши комментарии, эта проблема заставляет меня свалиться на дампы. – user2304993

ответ

1

Есть несколько вещей, которые я хотел бы указать. Первый, ваша ошибка:

I get a 'Notice: Trying to get property of non-object' from line 116 which is: $row_cnt = $result->num_rows;.

При вызове mysqli->query() с запросом на выборку, который не находит никаких результатов, то возвращаемый объект не является объектом, но вместо этого false.

Второй, а не COUNT(*), просто используйте *.

Таким образом, чтобы поддерживать свою логику, вы должны сделать что-то вроде этого:

//Check to see if user already voted 
$result = $conn->query("SELECT * FROM User_Votes where UserID = '$ip_long' and QuestionID = '$id'"); 

if ($result === false) { 
    //Add IP Address and ID to the User_Votes table 
    $result = $conn->query("INSERT INTO `User_Votes` (`UserID`, `QuestionID`) VALUES ('$ip_long', '$id')"); 
}elseif($result && $result->num_rows) { 
    //The user has already voted 
    echo "Already voted"; 
} 

Отредактировано:

//Check to see if user already voted 
$result = $conn->query("SELECT * FROM User_Votes where UserID = '$ip_long' and QuestionID = '$id'"); 

if($result->num_rows){ 
    //The user has already voted 
    echo "Already voted"; 
}else{ 
    //Add IP Address and ID to the User_Votes table 
    $result = $conn->query("INSERT INTO User_Votes (UserID, QuestionID) VALUES ('$ip_long', '$id')"); 
} 

Re отредактирован:

Вы должны вызвать $stmt->store_result() после $stmt->execute(). И ваш $stmt->get_result() здесь лишний, потому что вы не используете выбранные данные.

Часть комментария от documentation:

If you do not use mysqli_stmt_store_result(), and immediatley call this function after executing a prepared statement, this function will usually return 0 as it has no way to know how many rows are in the result set as the result set is not saved in memory yet.

Так что ваш код должен быть таким:

if(isset($_GET['id']) && !empty($_GET['id'])){ 
    $id = $_GET['id']; 
    $ip_long = ip2long($ip); 

    //Check to see if user already voted 
    $stmt = $conn->prepare("SELECT * FROM User_Votes where UserID = ? and QuestionID = ?"); 
    $stmt->bind_param('ss', $ip_long, $id); 
    $stmt->execute(); 
    $stmt->store_result(); 
    if($stmt->num_rows){ 
     //The user has already voted 
     echo "Already voted"; 
    }else{ 
     //Add IP Address and ID to the User_Votes table 
     $stmt = $conn->prepare("INSERT INTO User_Votes (UserID, QuestionID) VALUES (?, ?)"); 
     $stmt->bind_param('ss', $ip_long, $id); 
     $stmt->execute(); 
     $stmt = $conn->prepare("UPDATE Question SET QuestionVotes = QuestionVotes + 1 where QuestionID = ?"); 
     $stmt->bind_param('s', $id); 
     $stmt->execute(); 
    } 
} 

Sidenote: Пожалуйста, не путайте процедурный и объектно-ориентированного стиля mysqli.

+0

SELECT COUNT (*) всегда возвращает результат ... – jcaron

+0

@jcaron Это правильно. –

+0

Спасибо за ваш ответ, однако проблема заключается в том, что независимо от того, что без кавычек вокруг $ ip_long и $ ip, запрос возвращает false каждый раз и никогда не будет true. Таким образом, ваше изменение может быть правильным, но все-таки есть проблема, так или иначе связанная с запросом. – user2304993

0

В вашей инструкции вставки используются одинарные кавычки для включения переменных. Это должны быть двойные кавычки, поэтому PHP будет интерпретировать ваши переменные как значения вместо литеральной строки.

Это, по-видимому, является основной причиной происходящего. Могли ли вы проверить, правильно ли все было записано в таблицы базы данных, прежде чем вытащить их на работу? Затем проверьте, что ваш оператор select правильно вынимал данные и какую форму занимали данные?

И комментарий jcaran правильный. Некоторая проверка переменных, которые вы захватите, нужно будет рассмотреть.

+0

Все правильно отправляется в базу данных, да. хорошая информация, это, к сожалению, не является причиной проблемы. – user2304993

1

Вы должны проверить имя своей таблицы.

Вы используете это в одном из запросов User_Votes и этом user_votes в другом. Он может работать на вашем сервере разработки, если он работает под управлением Windows, которые нечувствительны к регистру, но Linux, который, вероятно, позволяет обрабатывать ваш производственный сервер с учетом регистра.

Проверить этот вопрос для получения дополнительной информации: Are table names in MySQL case sensitive?

Также обратите внимание, что из приведенной выше коды, ваше приложение выглядит небезопасно для инъекции SQL. Вы должны использовать переменные для int или что вы ожидаете от них.

+0

Информация передается в базу данных правильно, поэтому я боюсь, что чувствительность к регистру не является корнем проблемы. Но я рад, что вы обратили мое внимание на эту ошибку, я немедленно ее поменяю. – user2304993

+0

Как вы знаете, информация правильно передается в базу данных? – jcaron

 Смежные вопросы

  • Нет связанных вопросов^_^