Удаление доступа к голосованию для определенного объекта в зависимости от IP-адреса, сохраненного в базе данных.

Я попытался сделать несколько сообщений об этой проблеме, но решил собрать все в этом последнем, чтобы, надеюсь, как-то решить ее.

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

Во-первых, я получаю идентификатор и 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, устраняет проблему в локальном хосте, но не на моем сервере.

Местный var_dump($result) с кавычками вокруг переменных возвращает следующее:

object (mysqli_result) # 2 (5) {[«current_field»] => int (0) [«field_count»] => int (1) [«lengths»] => NULL [«num_rows»] => int (1 ) [«type»] => int (0)}

Я хотел бы добавить 1 к Вопросам для голосования по конкретному вопросу, а затем убрать возможность голосовать за тот же вопрос за конкретный 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) (pk), QuestionHeader (varchar (20)), QuestionText (текст), QuestionVotes (int (5))
User_Votes: UserID (без знака, int (39)), QuestionID (int (11))

0

Решение

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

Я получаю «Уведомление: пытаюсь получить свойство не-объекта» из строки 116, которая выглядит так: $ 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() здесь не нужно, потому что вы не используете выбранные данные.

Часть комментария от документация:

Если вы не используете mysqli_stmt_store_result () и немедленно вызываете эту функцию после выполнения подготовленного оператора, эта функция обычно возвращает 0, так как не может узнать, сколько строк в наборе результатов, поскольку набор результатов не сохраняется в памяти еще.

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

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();
}
}

Примечание: Пожалуйста, не смешивайте процедурный и объектно-ориентированный стиль mysqli,

2

Другие решения

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

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

Проверьте этот вопрос для получения дополнительной информации: Являются ли имена таблиц в MySQL чувствительными к регистру?

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

1

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

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

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

0
По вопросам рекламы [email protected]