使用 PHP 和 jQuery 的无限滚动分页只返回很少的帖子并使用加载器 gif 停止

Posted

技术标签:

【中文标题】使用 PHP 和 jQuery 的无限滚动分页只返回很少的帖子并使用加载器 gif 停止【英文标题】:Infinite Scroll Pagination using PHP and jQuery returns only few posts and halts with a loader gif 【发布时间】:2021-01-27 12:14:48 【问题描述】:

我正在尝试使用 php 和 JQuery 复制在线找到的无限滚动代码。

但不幸的是,代码中存在一个缺陷,它只返回 7 个帖子,并且在向下滚动时停止获取其他帖子,并在底部留下一个加载器 gif。

一般来说,我不会问这个问题,但代码似乎 非常好(用外行的话),我认为这会很有帮助 对于社区中像我这样的新手。

同时会搜索其他资源并尝试自己回答。

我的代码如下:

Index.php

<div class="post-wall">
        <div id="post-list">
            <?php
            require_once ('db.php');
            $sqlQuery = "SELECT * FROM tbl_posts";
            $result = mysqli_query($conn, $sqlQuery);
            $total_count = mysqli_num_rows($result);
            
            $sqlQuery = "SELECT * FROM tbl_posts ORDER BY id DESC LIMIT 7";
            $result = mysqli_query($conn, $sqlQuery);
            ?>
            <input type="hidden" name="total_count" id="total_count"
            value="<?php echo $total_count; ?>" />

            <?php
            while ($row = mysqli_fetch_assoc($result)) 
                $content = substr($row['content'], 0, 100);
                ?>
                <div class="post-item" id="<?php echo $row['id']; ?>">
                    <p class="post-title"><?php echo $row['title']; ?></p>
                    <p><?php echo $content; ?></p>
                </div>
                <?php
                
                ?>
            </div>
            <div class="ajax-loader text-center">
                <img src="LoaderIcon.gif"> Loading more posts...
            </div>
    </div>

<script type="text/javascript">
$(document).ready(function()
        windowOnScroll();
);
function windowOnScroll() 
       $(window).on("scroll", function(e)
        if ($(window).scrollTop() == $(document).height() - $(window).height())
            if($(".post-item").length < $("#total_count").val()) 
                var lastId = $(".post-item:last").attr("id");
                getMoreData(lastId);
            
        
    );


function getMoreData(lastId) 
       $(window).off("scroll");
    $.ajax(
        url: 'getMoreData.php?lastId=' + lastId,
        type: "get",
        beforeSend: function ()
        
            $('.ajax-loader').show();
        ,
        success: function (data) 
               setTimeout(function() 
                $('.ajax-loader').hide();
            $("#post-list").append(data);
            windowOnScroll();
               , 1000);
        
   );

</script>

getMoreData.php

<?php
require_once('db.php');

$lastId = $_GET['lastId'];
$sqlQuery = "SELECT * FROM tbl_posts WHERE id < '" .$lastId . "' ORDER BY id DESC LIMIT 7";

$result = mysqli_query($conn, $sqlQuery);


while ($row = mysqli_fetch_assoc($result))
 
    $content = substr($row['content'],0,100);
    ?>
    <div class="post-item" id="<?php echo $row['id']; ?>">
        <p class="post-title">  <?php echo $row['title']; ?></p>
        <p><?php echo $content; ?></p>
    </div>
    <?php

?>

非常感谢任何帮助。

【问题讨论】:

此代码极易受到sql injection 的影响。你应该使用prepared statements with parameter binding。 您能否在您的 getMoreData 方法的顶部添加一个 console.log('test'); 并使用打开控制台的页面检查日志?该消息打印了多少次?很多吗?还是只有几次? @HarryK 正如上面提到的@Wesley,将console.log('test'); 放在getMoreData 的顶部,看看你是否在控制台中收到消息。此外,在 Network 选项卡中,您应该会看到您的 ajax 调用并查看其请求和响应正文。 您在控制台中看到“test”打印了多​​少次? "above getMoreData function" 将是错误的位置,请将其添加到 getMoreData 方法的顶部但在函数内部。我们的想法是查看该方法被调用了多少次 【参考方案1】:

我会使用类和控制器等进行不同的设置,但作为简单的脚本,我可能会设置如下:

使用以下内容创建一个名为 getData.php 的文件:

<?php

require_once('db.php');

if (! function_exists('getData')) 
    /**
     * @param int $offset
     * @param int $limit
     * @return array|null
     */
    function getData($offset, $limit, $conn) 
         $offset = (int)$offset;
         $limit  = (int)$limit;
         $sqlQuery = "SELECT * FROM tbl_posts ORDER BY id DESC LIMIT $limit OFFSET $offset";
         $result = mysqli_query($conn, $sqlQuery);
         $rows = [];
         while ($row = mysqli_fetch_assoc($result)) 
             $rows[]= $row;
         
         return $rows;
     

使用此内容创建另一个名为 index.php 的文件:

<?php
require_once ('getData.php');

$offset = (int)($_GET['offset'] ?? 0);
$dataOnly = (int)($_GET['dataOnly'] ?? 0);
$limit = 7;
$rows = getData($offset, $limit, $conn);
$offset+= $limit;
$data = [
    'rows' => $rows,
    'offset' => $offset,
];


$data = json_encode($data);

// if this is an ajax call, stop here and just spit out our json
if ($dataOnly) 
    echo $data;
    exit;

// otherwise, render the page
$sqlQuery = "SELECT * FROM tbl_posts";
$result = mysqli_query($conn, $sqlQuery);
$total_count = mysqli_num_rows($result);
?>

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="jquery-3.2.1.min.js"></script>
    <style type="text/css">
        body 
            font-family: Arial;
            background: #e9ebee;
            font-size: 0.9em;
        

        .post-wall 
            background: #FFF;
            border: #e0dfdf 1px solid;
            padding: 20px;
            border-radius: 5px;
            margin: 0 auto;
            width: 500px;
        

        .post-item 
            padding: 10px;
            border: #f3f3f3 1px solid;
            border-radius: 5px;
            margin-bottom: 30px;
        

        .post-title 
            color: #4faae6;
        

        .ajax-loader 
            display: block;
            text-align: center;
        
        .ajax-loader img 
            width: 50px;
            vertical-align: middle;
        
    </style>
</head>
<body>
<div class="post-wall">
    <div id="post-list">
        <input type="hidden" name="total_count" id="total_count" value="<?= $total_count ?>" />
        <input type="hidden" name="offset" id="offset" value="<?= $offset ?>" />
    </div>
    <div class="ajax-loader text-center">
        <img src="LoaderIcon.gif"> Loading more posts...
    </div>
</div>

<script type="text/javascript">
    $(document).ready(function()
// load the initial rows on page load
        let initialData = <?= $data ?? '' ?>;
        if (initialData) 
            if (initialData.rows) 
                addrows(initialData.rows);
                $('.ajax-loader').hide();
            
        
        windowOnScroll();

    );
    function windowOnScroll() 
        $(window).on("scroll", function(e)
            if ($(window).scrollTop() == $(document).height() - $(window).height())
                console.log('test');
                if($(".post-item").length < $("#total_count").val()) 
                    let offset = $('#offset').val();
                    getMoreData(offset)
                
            
        );
    

    function getMoreData(offset) 
        $('.ajax-loader').show();
        $(window).off("scroll");
        let pageUrl = window.location.href.split('?')[0];
        $.ajax(
            url: pageUrl + '?dataOnly=1&offset=' + offset,
            type: "get",
            success: function (response) 
                response = JSON.parse(response);
                if (response.rows) 
                    addrows(response.rows);
                    if (response.offset) 
                        $('#offset').val(response.offset);
                    
                    $('.ajax-loader').hide();
                
                windowOnScroll();
            
        );
    

    function addrows(rows) 
        let postList = $("#post-list");
        $.each(rows, function (i, row) 
            let rowHtml = '<div class="post-item" id="'+row.id+'"><p class="post-title">'+row.title+'</p><p>'+row.content+'</p></div>';
            postList.append(rowHtml);
        );
    
</script>
</body>
</html>

现在,我无法在本地对此进行测试,因此可能会出现一两个错误,但这应该可以让您大致了解。

我不能 100% 确定的是 if ($(window).scrollTop() == $(document).height() - $(window).height()) 条件。

XSS 警告

您没有展示这些“帖子”是如何添加到数据库中的,可能它们来自用户在其他表单上提交的内容。如果是这种情况,请确保您了解what XSS vulnerabilities are and how to prevent them

【讨论】:

你在那儿,兄弟。有个小疑问。 有什么问题? 你能访问一下吗..chat.***.com/rooms/222945/…

以上是关于使用 PHP 和 jQuery 的无限滚动分页只返回很少的帖子并使用加载器 gif 停止的主要内容,如果未能解决你的问题,请参考以下文章

php 使用Laravel和jScroll进行无限滚动分页

如何使用 jQuery Masonry 添加无限滚动?

如何对 Infinite Scroll 的查询结果进行分页?

如何使用图像视图制作无限分页滚动视图?

当没有更多数据时如何停止无限循环(分页)

带缓存的无限/分页滚动