I can call the code but for some reason it keeps calling the same rows over and over, is there a way keep track of rows called?

example
https://gotsocial.co.uk/business-view.php?id=4

Calling code

<script type="text/javascript">
	$(window).scroll(function() 
	{
		if($(window).scrollTop() + $(window).height() == $(document).height()) 
		{
			console.log("got here");
			// $('.load-results').load('get_records.php');	
			var getid = '<?php echo $_GET['id']; ?>';
			console.log(getid);
			var flag = 0;
			 $.ajax({
				url:'get_records.php',
				 data: {id: getid,
				 'offset': flag,
				 'limit': 3
				 },
				type:'get',
				success: function(data){
				$(".reviews-section").after(data);
				flag += 3;
			}
			});
		}
	});

</script>

php section

<?php


require("classes/Database.php");
$db       = new Database;
$get      = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
$business = $get['id'];
$limit    = 2;
$query    = "SELECT * FROM reviews  ORDER BY adressId DESC LIMIT 8";

$s = $db->prepare($query);
$s->execute();
$total_results = $s->rowCount();
$total_pages   = ceil($total_results / $limit);

if (!isset($_GET['page'])) {
    $page = 1;
} else {
    $page = $_GET['page'];
}

$starting_limit = ($page - 1) * $limit;


$query = "
            SELECT s.town, s.street, s.streetNumber, s.region, s.postcode, s.businessName, s.business, s.adressId, s.town, r.userId, r.review, s.phone, s.lat, s.lon, u.username
            FROM shopAddress as s
            INNER JOIN reviews AS r ON s.adressId=s.adressId
            INNER JOIN users AS u ON r.userId=u.userId
            WHERE s.adressId = :business LIMIT $starting_limit, $limit";
$s     = $db->prepare($query);
$s->bindValue(':business', $business);
$s->execute();
//            $total_results = $s->rowCount();


foreach ($s as $review) {
?>    
<section class="user-review">
<div class="review-username"><a href="#"><?php print $review['username']; ?></a></div> <div class="user-rating"><div class="rating"></div></div> <p class="review-output"> <?php print $review['review']; ?> </p>
</section>
<?php }

    I wonder if this isn't a case of "bad data" appearing to be repeating. I know during testing we tend to use the same generic filler data over and over; however, sometimes that leads to us seeing problems that don't actually exist.

    I would change the following items:

    1. You pass an offset and a limit to your PHP script via the query string parameters; however, you seem to ignore them in the actual PHP ($_GET['page'] isn't passed in and $limit is hard-coded).
    2. You create "generic" sections for each user review. I would instead add an id or some data attribute to provide me the ability to uniquely tag each review in the code for easier debugging. E.g.: <section class="user-review" data-review="<?= $review['id'] ?>">
    3. Since the starting / limits seem to be passed in via the query string, I would also bind them as parameters or sanitize them prior to their use.
    4. Return the raw JSON of the data to be displayed and allow javascript to generate the HTML. This way if an empty result is returned, I can turn off the AJAX call or repeat the correct offset so the inflation of the offset number stops.
      [upl-image-preview url=https://board.phpbuilder.com/assets/files/2019-03-29/1553827678-3346-capture.png]

    With just the second change, you'd be able to see if your data was in fact that repetitive or if the script is having a problem and returning the incorrect values. Once you get high enough in the offset value, results just stop being returned.

    Oh I eventually changed it to this, it seems to work although I'm not sure if it's completely secure

    PHP

    <?php
    if(isset($_GET['offset']) && isset($_GET['limit'])){
    $limit = $_GET['limit'];
    $offset = $_GET['offset'];
    $get = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);		
    $business = $get['id'];
    		
    require("classes/Database.php");
    $db = new Database;
    $query = "SELECT s.town, s.street, s.streetNumber, s.region, s.postcode, s.businessName, 
           s.business, s.adressId, s.town, r.userId, r.review, r.reviewTitle,s.phone, s.lat, s.lon, u.username, 
           u.profileImgPath
    	FROM shopAddress as s
    	INNER JOIN reviews AS r ON s.adressId=s.adressId
    	INNER JOIN users AS u ON r.userId=u.userId
    	WHERE s.adressId = :business LIMIT {$limit} OFFSET {$offset}";	
    	$s = $db->prepare($query);
    	$s->bindValue(':business', $business);  
    $s->execute(); foreach($s as $review){ ?> <section class="user-review"> <div class="review-profile"><a href="#"><img src="../../../<?php print htmlspecialchars($review['profileImgPath']); ?>" alt="user profile image"></a></div> <div class="user-rating"><div class="rating"></div></div> <div class="review-username"><a href="#"><?php print htmlspecialchars($review['username']); ?></a></div> <p class="review-output"><?php print htmlspecialchars($review['review']); ?></p> </section> <?php } }

    Ajax

    <script type="text/javascript">
    	
    $(document).ready(function(){
    
    var flag = 0;
    var getid = '<?php echo $_GET['id']; ?>';
    $.ajax({
    	type:"GET",
    	url:"get_records.php",
    	data: {
    		id: getid,
    		'offset': 0,
    		'limit': 8
    	},
    	success: function(data){
    		$('.reviews-section').append(data);
    		flag += 6;
    	}
    });
    
    $(window).scroll(function(){
    if($(window).scrollTop() >= $(document).height() - $(window).height()){
    
    var getid = '<?php echo $_GET['id']; ?>';
    $.ajax({
    	type:"GET",
    	url:"get_records.php",
    	data: {
    		id: getid,
    		'offset': flag,
    		'limit': 8
    	},
    	success: function(data){
    		$('.reviews-section').append(data).fadeIn("1000");
    		flag += 6;
    	}
    });
    
    }
    	
    });
    
    });	
    
    </script>
    
      21 days later

      Any time you're dealing with input from an "external" source (e.g. a parameter from a request) you should validate that it meets your expectations and escape it or cast it to a type. In this case, you could easily just pass the $_GET variables to intval to cast non-numeric strings to a numeric value (e.g. 10' -- whatever becomes 10).

      I'll reiterate the practice of adding identifiers to your output that you can link to your data. Even a simple data-rid="<?= $review['id'] ?>" on the <section> element would be enough to identify if you're looping through the same data, or if you're getting fresh data.

      Glad you got it sorted though.

      data-rid="<?= $review['id'] ?>"
      

      Ah thanks, I must have missed that it makes sense

        Write a Reply...