I have tried making a few posts about this problem, but have decided to collect everything in this final one to hopefully somehow solve it.
I am building a site where users can vote on questions from a database. There's no login and so, to make sure everyone can only vote once per question, I am using their IP together with the ID of the question.
First, I get the ID and IP address and store both, making sure they are integers:
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);
I then check to see if the user has already votes, using the two variables. This is where I expect the problem arises. I get a:
Notice: Trying to get property of non-object
from line 116 which is: $row_cnt = $result->num_rows
.
Furthermore var_dump ($result)
returns bool(false)
and var_dump ($row_cnt)
returns Null
. Adding quotes around the two variables in the query, $ip_long and $id fixes the problem while localhost, but not on my server.
A local var_dump($result)
with quotes around the variables returns the following:
object(mysqli_result)#2 (5) { ["current_field"]=> int(0) ["field_count"]=> int(1) ["lengths"]=> NULL ["num_rows"]=> int(1) ["type"]=> int(0) }
I would like to add 1 to the QuestionVotes for the specific question and then remove the option to vote on that same question for the specific IP Address.
//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();
}
}
And lastly, here is the code I use to build the html boxes containing database question information, add a voting button that displays the current votes and append, what is used as QuestionID, to the 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";
}
My tables are as follows:
Question: QuestionID(int11)(pk), QuestionHeader(varchar(20)), QuestionText(text), QuestionVotes(int(5))
User_Votes: UserID(unsigned, int(39)), QuestionID(int(11))