Stop User From Liking Post Multiple Times - php

I have a like button, which allows users to like posts on my site. If the user likes a post they have not liked before it will +1, if they press the same like button again it will -1. This is working on my virtual server on my laptop. However, the same code is not working on my live site. On my live site the user is able to like the same post multiple times, which is not what I want. I'm using a JQuery Ajax call to a PHP file that fires a some MySQL code.
Can anyone see anything obviously wrong with the PHP below?
include ("../con/config.php");
$postid = $_POST['postid'];
$userid = $_POST['userid'];
$query = $con->prepare("SELECT COUNT(*) AS CntPost FROM Likes WHERE UserID = ? AND PostID = ?");
$query->bind_param('ss',$userid,$postid);
$query->execute();
$result = $query->get_result();
$fetchdata = $result->fetch_assoc();
$count = $fetchdata['CntPost'];
if($count == 0){
$stmt = $con->prepare("INSERT INTO Likes(UserID,PostID) VALUES(?,?)");
$stmt->bind_param("ss", $userid, $postid);
$stmt->execute();
} else {
$stmt = $con->prepare("DELETE FROM Likes WHERE UserID = ? AND PostID = ?");
$stmt->bind_param("ss", $userid, $postid);
$stmt->execute();
}
// count numbers of likes in post
$query = $con->prepare("SELECT COUNT(*) AS CntLike FROM Likes WHERE PostID = ?");
$query->bind_param('s', $postid);
$query->execute();
$result = $query->get_result();
$fetchlikes = $result->fetch_assoc();
$totalLikes = $fetchlikes['CntLike'];
$return_arr = array("likes"=>$totalLikes,"type"=>$count);
echo json_encode($return_arr);

Managed to solve it. The issue was in the MySQL database column itself for the UserID. The number of chars for the column was not long enough and was truncating the UserID, which I populate using the sessionID. I amended this field in the database to allow for the length of a sessionID.

perhaps this statement
"SELECT COUNT(*) AS CntLike FROM Likes WHERE PostID = ?" need UserID in WHERE statement so you would know that specific UserID in that specific PostID

Related

How can I delete a like from my database if user_id and post_id are the same?

I want to check if user already liked the post, if so than delete the user from database likes.
I've tried to do an if statement but it wont get to the else and only add likes even when user_id and post_id are the same.
Like.class.php
private function Addlike(){
$conn = db::getInstance();
$query = "insert into likes (post_id, user_id) values
(:post_id, :user_id)";
$statement = $conn->prepare($query);
$statement->bindValue(':post_id',$this->getPostId());
$statement->bindValue(':user_id',$this->getUserId());
$statement->execute();
}
private function Deletelike(){
$conn = db::getInstance();
$query = "DELETE FROM likes WHERE post_id = :post_id
AND user_id =:user_id";
$statement = $conn->prepare($query);
$statement->bindValue(':post_id',$this->getPostId());
$statement->bindValue(':user_id',$this->getUserId());
$statement->execute();
}
public function CheckLike(){
$conn = db::getInstance();
$query = "SELECT COUNT(*) FROM likes WHERE
post_id=:post_id AND user_id=:user_id";
$statement = $conn->prepare($query);
$statement->bindValue(':post_id',$this->getPostId());
$statement->bindValue(':user_id',$this->getUserId());
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
if($result["COUNT(*)"] == 0){
$this->Addlike();
}else{
$this->Deletelike();
}
return $result;
}
If you press like for the first time you should like the post and it should be stored in the database, if you press again you unlike the post and it gets deleted from the database. But now it only does the Addlike function...
I think PDO::FETCH_ASSOC returns a multidimensional array when used with PDOStatement::fetchAll, according to https://www.php.net/manual/en/pdostatement.fetchall.php#refsect1-pdostatement.fetchall-examples.
Try changing your code to something like this and see if it works. You could also try dumping the $result variable to see what the structure looks like.
if($result[0]["COUNT(*)"] == 0){
$this->Addlike();
}else{
$this->Deletelike();
}
If an array index doesn't exist, PHP considers it false, which would explain why you're always adding likes, since false == 0 in PHP.
If you want to avoid this equivalency of false and 0, use the identical operator to also compare types:
if ($result["COUNT(*)"] === 0) {
...

PHP while() function is running my query 3 times

My problem is that:
I have a users table in MySQL. I made a query with MySQLi which looks like:
if($stmt = $mysqli->prepare("SELECT condition,name,money FROM users WHERE fbid = ?")){
$stmt->bind_param('s',$_SESSION['FBID']);
$stmt->execute();
$stmt->store_result();
$num_of_rows = $stmt->num_rows;
$stmt->bind_result($condition,$name,$money);
while ($stmt->fetch()) {
And here's my problem, because I want different users to add equal usernames to their ids. So, my code is the following:
if($_GET['name']!='' && $money>'500'){
$stmt2 = $mysqli->prepare("UPDATE users SET `condition` = `condition` + 5, `money` = `money` - 5 WHERE fbid = ? AND name = ?");
$stmt2->bind_param("ss", $_SESSION['FBID'],$_GET['name']);
$stmt2->execute();
$stmt2->close();
I want to update only that value in the database where user ID = $_SESSION[fbid] and name = $_GET[name]. So if I have an account with id 1922838445 and I have three names, for example, John, Joe, and Jill and $_GET[name]=='Joe' then update only that value at the same ids. It works until that point that update only the got value, but it does that 3 times... Because of while () maybe??? How can I fix it?
The two code samples have to come one after!! Because of checking the value of money..
There's no need for the first SELECT and the loop, just put the condition on money into the UPDATE query itself.
if ($_GET['name'] != '') {
$stmt = $mysqli->prepare("
UPDATE users
SET condition = condition + 5, money = money - 5
WHERE fbid = ? AND name = ?
AND money > 500")
$stmt->bind_param("ss", $_SESSION['FBID'], $_GET['name']);
$stmt->execute();
}
Try this instead to get only one record:
It gets only the record you need because it has a WHERE clause on both parameters that you plan to update, instead of only a partial match on the fbid like you had before.
Before you were getting 3 records because you had a partial key search, then looping through the records and updating the same record over and over against, regardless of the value of the second part of the key in the record you were looping against.
if($stmt = $mysqli->prepare("SELECT condition,name,money FROM users WHERE fbid = ? AND name = ?")){
$stmt->bind_param("ss", $_SESSION['FBID'],$_GET['name']);
$stmt->execute();

php pdo : update + insert and then select returns null

For some reason this php code on execution is returning NULL...cud any1 kindly help in correcting it?
public function like($pid)
{
$uid = escape($_SESSION['user']);
$sql = $this->_db->prepare("UPDATE postsinitial SET likes = likes+1 WHERE pid = :m;INSERT IGNORE INTO userlikedposts (ulp_userid,ulp_postid) VALUES (:k, :m)");
$sql->bindValue(':k', $uid);
$sql->bindValue(':m', $pid);
$sql->execute();
$query = $this->_db->prepare("SELECT likes FROM postsinitial WHERE pid = :n");
$query->bindParam(':n', $pid);
$query->execute();
while($rows = $query->fetch())
{
return $rows['likes'];
}
}
But when i run the two parts of the query separately, i.e., commenting out the $sql batch of code and running $query batch alone, it works and returns a value.. , it works fine..but not combined as stated..so how do i run it as is?
I've tried this model too for the select query bt still same result:
$query = $this->_db->prepare("SELECT likes FROM postsinitial WHERE pid = :n");
$query->bindParam(':n', $pid);
$query->execute();
while($rows = $query->fetch(PDO::FETCH_ASSOC))
{
return $rows[0]['likes'];
}
The answer is simple:
You should run your queries one by one instead of stuffing them all into a single call. Run your insert query separated rom update and you'll be fine.
public function like($pid)
{
$sql = "UPDATE postsinitial SET likes = likes+1 WHERE pid = ?";
$this->_db->prepare($sql)->execute($_SESSION['user']);
$sql = "INSERT IGNORE INTO userlikedposts (ulp_userid,ulp_postid) VALUES (?, ?)";
$this->_db->prepare($sql)->execute([$_SESSION['user'], $pid]);
$stmt = $this->_db->prepare("SELECT likes FROM postsinitial WHERE pid = ?");
$stmt->execute([$pid]);
return $stmt->fetchColumn();
}

Update rows after mysql select foreach

I have a select where I have 3 results:
$stmt = $handler->prepare("SELECT id,comments,likes,views FROM sites WHERE usr_id = '$usr_id'");
$stmt->execute();
After this select I have 3 results. Now I want in another table update or insert a new row for each result
This is my complete code
I don't have any update or new insert in table. Can anybody please help me?
$stmt = $handler->prepare("SELECT id,comments,likes,views FROM sites WHERE usr_id = '$usr_id'");
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$rows[]=$row;
foreach($rows as $row){
$site_id = $row[id];
$stmt = $handler->prepare("SELECT id FROM session WHERE site_id = '$site_id' AND usr_id = '$usr_id'");
$stmt->execute();
$no=$stmt->rowCount();
if ($no > 0)
{
$stmt = $handler->prepare("UPDATE session SET comments = '$comments' , likes = '$likes' , views = '$views' WHERE usr_id = $usr_id AND site_id = $site_id");
$stmt->execute();
}
else
{
$stmt = $handler->prepare("INSERT INTO session(user_id,site_id,comments,likes,views)VALUES('$user_id','$site_id','$comments','$likes','$views')");
$stmt->execute();
}
}
}
First issue, you weren't taking advantage of prepared statements at all. Use parameters (the ? in the query) and then fill them with values in the execute() call.
Also, prepare your query outside a loop, and execute it inside. This is one of the key advantages of preparing statements in advance, there is less overhead when they are only prepared once.
Finally, there's no need for checking the database before your query and then executing one of two queries. Just let MySQL check if the value exists already with INSERT...ON DUPLICATE KEY UPDATE syntax. This relies on the database being set up properly, so there should be a UNIQUE index on (session.usr_id, session.site_id).
This is untested, but should get you going:
$stmt1 = $handler->prepare("SELECT id,comments,likes,views FROM sites WHERE usr_id = ?");
$stmt2 = $handler->prepare("INSERT INTO session SET comments = ?, likes = ?, views = ?, usr_id = ?, site_id = ? ON DUPLICATE KEY UPDATE comments = VALUES(comments), likes = VALUES(likes), views = VALUES(views)");
$stmt1->execute(array($usr_id));
while($row = $stmt1->fetch(PDO::FETCH_ASSOC)) {
$site_id = $row["id"];
$stmt2->execute(array($comments, $likes, $views, $usr_id, $site_id));
}
#Miken32's answer would be the ideal way.
A direct fix to your code would be this way:
$stmt1 = $handler->prepare("SELECT id,comments,likes,views FROM sites WHERE usr_id = :usr_id");
$stmt1->bindValue(':usr_id', $usr_id);
$stmt1->execute();
while ($row = $stmt1->fetch(PDO::FETCH_ASSOC)) {
$stmt2 = $handler->prepare("SELECT id FROM session WHERE site_id = :site_id AND usr_id = :usr_id");
$stmt2->bindValue(':usr_id', $usr_id);
$stmt2->bindValue(':site_id', $row['id']);
$stmt2->execute();
if ($stmt2->rowCount() > 0) {
$stmt3 = $handler->prepare("UPDATE session SET comments = :comments , likes = :likes , views = :views WHERE usr_id = :usr_id AND site_id = :site_id");
} else {
$stmt3 = $handler->prepare("INSERT INTO session(user_id,site_id,comments,likes,views)VALUES(:usr_id,:site_id,:comments,:likes,:views)");
}
$stmt3->bindValue(':comments', $row['comments']);
$stmt3->bindValue(':likes', $row['likes']);
$stmt3->bindValue(':views', $row['views']);
$stmt3->bindValue(':usr_id', $usr_id);
$stmt3->bindValue(':site_id', $row['id']);
$stmt3->execute();
}
But this is not the best way to go about it. INSERT ...UPDATE ON DUPLICATE KEY would be better.

Not getting a result from DB

So I'm checking to see if a user already liked a post. Here's what I'm doing
$id = 65;
//Get likes count
$stmt = $con->prepare("SELECT * FROM likes WHERE liked_post_id = :liked_post_id");
$stmt->bindValue(':liked_post_id', $id, PDO::PARAM_STR);
$stmt->execute();
$return = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<pre>
<?php
print_r($return);
?>
</pre>
<?php
//Get user IP
$ip = $_SERVER['SERVER_ADDR'];
//Check if user liked post
$result = $con->prepare("SELECT * FROM likes WHERE liked_post_user = :username");
$result->bindParam(':username', $_SESSION['user']);
$result->execute();
$reprint = $result->fetch(PDO::FETCH_ASSOC);
echo $reprint['liked_post_user'];
$return_cnt = count($reprint);
if($return_cnt < 1){
//Insert like
$query = $con->prepare("INSERT INTO likes (liked_post_id, liked_post_user, liked_post_ip) VALUES (:usr_id, :user, :ip)");
$query->bindValue(':usr_id', $id, PDO::PARAM_STR);
$query->bindValue(':user', $_SESSION['user']);
$query->bindValue(':ip', $ip, PDO::PARAM_STR);
$query->execute();
}
The problem is $query never gets ran. Even though I have no record of the username in the DB. So I'd expect it to run once, and insert $query into the DB, once. But it isn't. I'm not getting any errors either. Any ideas?
First of all you can simply count $reprint. To answer your second issue, you need to select the post, or else it'll simply check all the posts. So do
$result = $con->prepare("SELECT * FROM likes WHERE liked_post_user = :username AND liked_post_id = :post_id");
$result->bindParam(':username', $_SESSION['user']);
$result->bindParam(':post_id', $_GET['id']);
$result->execute();
$reprint = $result->fetch(PDO::FETCH_ASSOC);
Note that if no user is logged in it'll still input an empty value. So make sure to figure a way around that.
The second query should look for a specific liked_post_id. It's currently looking for any posts that the user liked, not just this one.
//Check if user liked post
$result = $con->prepare("SELECT * FROM likes WHERE liked_post_user = :username AND liked_post_id = :id");
$result->bindParam(':username', $_SESSION['user']);
$result->bindParam(':id', $id);
$result->execute();
$reprint = $result->fetch(PDO::FETCH_ASSOC);
And then you should test whether the query found anything by testing whether $reprint is an array or false:
if ($reprint) {
echo $reprint['liked_post_user'];
} else {
//Insert like
$query = $con->prepare("INSERT INTO likes (liked_post_id, liked_post_user, liked_post_ip) VALUES (:usr_id, :user, :ip)");
$query->bindValue(':usr_id', $id, PDO::PARAM_STR);
$query->bindValue(':user', $_SESSION['user']);
$query->bindValue(':ip', $ip, PDO::PARAM_STR);
$query->execute();
}

Categories