Я попытался сделать несколько сообщений об этой проблеме, но решил собрать все в этом последнем, чтобы, надеюсь, как-то решить ее.
Я создаю сайт, где пользователи могут голосовать по вопросам из базы данных. Нет логина и поэтому, чтобы все могли голосовать только один раз за вопрос, я использую их 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))
Есть несколько вещей, на которые я хотел бы указать. Первый, ваша ошибка:
Я получаю «Уведомление: пытаюсь получить свойство не-объекта» из строки 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
,
Вы должны проверить имя вашей таблицы.
Вы используете это в одном из запросов User_Votes
и это user_votes
в другом. Он может работать на вашем сервере разработки, если он работает на Windows, без учета регистра, но Linux, который, вероятно, обеспечивает работу вашего производственного сервера с учетом регистра.
Проверьте этот вопрос для получения дополнительной информации: Являются ли имена таблиц в MySQL чувствительными к регистру?
Также обратите внимание, что из приведенного выше кода ваше приложение выглядит небезопасным для внедрения SQL-кода. Вы должны привести переменные к int или к тому, что вы ожидаете от них.
Ваш оператор вставки использует одинарные кавычки для включения ваших переменных. Это должны быть двойные кавычки, поэтому PHP будет интерпретировать ваши переменные как значения, а не как буквальную строку.
Это выглядит как основная причина того, что происходит. Удалось ли вам проверить, все ли правильно записывалось в таблицы базы данных, прежде чем пытаться их обработать? Затем убедитесь, что ваш оператор выбора правильно извлекает данные и какую форму принимают данные?
И комментарий jcaran является правильным … необходимо будет рассмотреть некоторую проверку переменных, которые вы захватили.