-1

I have this page that consists of a list of user posts / message. When a post is liked, I want it to reflect on all other users, and based on my research setInterval can get the job done by refreshing a specific content for a number of seconds. Currently, I'm having trouble looping through all the user messages and show the updated number of likes. What's happening is that the number displayed is constantly changing and looping through all the values for a single post. Example: If I have 1, 0, and 2 likes respectively on three different posts, the number for the first post changes to 1, 0, and 2 instead of just showing "1". I'm kind of a beginner when it comes to AJAX.

Here's my code:

Jquery / Ajax

function refreshPostLikes() {
setInterval(function() {
$(".posts .id").each(function() {  //get id for each post
var postid = $(this).attr("value"); 
updatePostLikes(postid);  //pass the postid variable
});
}, 1000);
}


function updatePostLikes(postid) {
$.ajax({
url: "/main/refresh-post-like.php",
type: "post",
data: {postid: postid},  //send data to php file
success: function(data) {
$(".posts .like").html(data);  //output number of likes
}
});
}

PHP Query

<?php
require_once('../connection.php');

$postID = $_POST['postid'];

$likeCountQuery = "select count(*) as total_likes from posts_likes WHERE like_status=1 AND post_id=".$postID;  //query number of posts with a like
$likeQueryResult = mysqli_query($conn, $likeCountQuery);

while($likeNumber = mysqli_fetch_assoc($likeQueryResult)) {
$likes = $likeNumber['total_likes'];

if($likes != 0) {
echo $likes;
}
else {
echo '';
}
}
?>
user874737
  • 469
  • 1
  • 9
  • 24
  • #1 Think about if you really need that feature and if that is how you want to implement it. You might very easily end up killing your server (you check **all** posts on your page **every second** for **every user**) #2. can you confirm that your ajax call gets the right like counts ? #3 `$(".posts .like").html(data);` replaces the HTML of **all** elements that match that selector, you need to find the right one for the ID you send – Lapskaus Jun 15 '20 at 10:33
  • @Lapskaus, #1, is there any other way to do it? Or would it be better just not do it at all? #2, yes it does. #3, how? I tried adding .each() with $(".posts .like") but it still doesn't seem to work. – user874737 Jun 15 '20 at 10:39
  • It would be better to go the other way around, when a post is liked, catch that event and update the counters. – RST Jun 15 '20 at 10:39
  • @RST, yes I have that covered for the user who liked the post. But, I want the liked to appear to other users real time, hence I used setinterval to refresh that part. – user874737 Jun 15 '20 at 10:40
  • I do not think it is a good idea to do a request for each div. Collect them and do ONE request and update / populate from that response. – Markus Zeller Jun 15 '20 at 10:40
  • There are several ways to do this. What you are implementing right now is called [shortpolling](https://stackoverflow.com/questions/4642598/short-polling-vs-long-polling-for-real-time-web-applications) another client based way would be [longpolling](https://stackoverflow.com/questions/4642598/short-polling-vs-long-polling-for-real-time-web-applications). Another aproach are server pushes e.g. [server send events](https://stackoverflow.com/questions/7636165/how-do-server-sent-events-actually-work) or [websockets](https://stackoverflow.com/questions/43817850/understanding-of-websockets) – Lapskaus Jun 15 '20 at 10:44
  • @Lapskaus, thanks. I'm not familiar with those. I'll give them a review. What do you recommend for my design? – user874737 Jun 15 '20 at 10:48
  • @MarkusZeller, you mean there's no need for it to show the changes to other users unless they refresh the page? – user874737 Jun 15 '20 at 12:29
  • @user874737 No, I did not say that with any word. Read again :D – Markus Zeller Jun 15 '20 at 12:59
  • Ah, you mean I should do it in one go rather than to loop through them and execute the query for each. I see. @MarkusZeller – user874737 Jun 15 '20 at 13:45
  • Yes. Collect the IDs, make one request containing that. Then get a response with the data for all IDs and then put back to every div where IDs data changed. So you have only ONE request instead of x (lets say 20). This will speed up the connections (because 1 ist faster than 20), save the overhead.. – Markus Zeller Jun 15 '20 at 14:22

2 Answers2

0

Still not sure this is the best way to go, but the reason your code doesn't work is due to omitting the postid when updating the HTML in the success part of your code.

function updatePostLikes(postid) {
$.ajax({
url: "/main/refresh-post-like.php",
type: "post",
data: {postid: postid},  //send data to php file
success: function(data) {
$(".posts .like").html(data);  //output number of likes
}
});
}

with this command $(".posts .like").html(data); //output number of likes

You are updating all the divs which have these classes specified with the same value. Set postid as id for the div and change the command to

$("#postid").html(data); //output number of likes

RST
  • 3,899
  • 2
  • 20
  • 33
-1

is constantly changing and looping through all the values for a single post

This happens because there is no reference to the post that needs to be updated. What you are doing now is to cycle through all the elements that have the ".posts .id" classes, therefore the update applies to all the posts and not the single one. You should modify your function to make it update only that post (try passing it a unique id in html)

Where N is the id of your post. (For example postid)

Then update the value using this

function updatePostLikes(postid) {
    $.ajax({
        url: "/main/refresh-post-like.php",
        type: "post",
        data: {
            postid: postid
        }, //send data to php file
        success: function(data) {
            //$(".posts .like").html(data); //output number of likes
            $("#post-"+postid).html(data); // in this way we're get the right post
        }
    });
}

function refreshPostLikes() {
    $(".posts .id").each(function() { //get id for each post
        var postid = $(this).attr("value");
        updatePostLikes(postid); //pass the postid variable
    });

    setTimeout(refreshPostLikes, 1000); //Check every sec if there are update
}

setTimeout(updateChat, 1000); //Start the check 

Prevent SQL Injection Escape is not enough

<?php
require_once ('../connection.php');

$postID = $_POST['postid']; //Escape this value before use inside the query see linked question

// NEVER TRUST USER INPUT
//$likeCountQuery it could be used for perform a SQL Injection NEVER TRUST USER INPUT
//NEVER !!!
$likeCountQuery = "SELECT COUNT(*) AS total_likes FROM posts_likes WHERE like_status=1 AND post_id=".$postID;  //query number of posts with a like
$likeQueryResult = mysqli_query($conn, $likeCountQuery);

while ($likeNumber = mysqli_fetch_assoc($likeQueryResult))
{
    $likes = $likeNumber['total_likes'];

    if ($likes != 0)
    {
        echo $likes;
    }
    else
    {
        echo '';
    }
}
?>