MySQL PHP分页

3

我正在尝试使用PHP、MySQL和Bootstrap为客户表格使用分页。我编写了以下代码:

<div class="container mx-auto">
<!--Add class table-responsive for responsive table -->
<table class="table mx-auto">
    <thead>
    <tr>
        <th>Name</th>
        <th>Surname</th>
        <th>Email</th>
        <th>Phone</th>
        <th>Address</th>
        <th>Zipcode</th>
        <th>City</th>
        <th>Company</th>


    </tr>
    </thead>
    <tbody>
    <ul class="pagination">
        <?php
        if(isset($_GET['page'])){

            $previous = $_GET['page'] - 1;
            if($previous = -1 ){
                $previous = 0;
            }
            if($previous = 0){
                echo '<li class="page-item"><a class="page-link" href="#">Previous</a></li>';
            }
            else{
                echo '<li class="page-item"><a class="page-link" href="?page='. $previous.'">Previous</a></li>';
            }
        }
        $page_max = 10;
        $entriesInDatabase = $database->getData("SELECT count(id) FROM customers");
        $numberOfPages = ceil($entriesInDatabase['count(id)']/$page_max);

        for($i = 0; $i < $numberOfPages; $i++){

            echo '<li class="page-item"><a class="page-link" href="?page='. $i . '">'. $i. '</a></li>';
        }
        if(isset($_GET['page'])) {
            $page = $_GET['page'];
            $start = $page * 10;
            $end = ($page + 1) * 10;
            var_dump($start); 
            var_dump($end);
        }
        else{
            $page = 0;
            $start = $page * 10;
            $end = 10;
        }

        $customers = $database->getUsers("SELECT * FROM customers LIMIT $start, $end");

        ?>
        <li class="page-item"><a class="page-link" href="#">Next</a></li>
    </ul>
    <?php



    foreach($customers as $customer){
        $name = $customer ['name'];
        $surname = $customer['surname'];
        $email = $customer['email'];
        $phone = $customer['phone'];
        $address = $customer['address'];
        $zipcode = $customer['zipcode'];
        $city = $customer['city'];
        $company = $customer['company'];
        $id = $customer['id'];
        echo "<tr>
                <td>$name</td>
                <td>$surname</td>
                <td>$email</td>
                <td>$phone</td>
                <td>$address</td>
                <td>$zipcode</td>
                <td>$city</td>
                <td>$company</td>



              </tr>";
    }
    ?>

我希望每个页面从数据库中显示10条记录,因此我会在SQL查询中设置数据限制。现在的情况是这样的:第0页显示10条记录,第1页显示20条记录,第2页也显示20条记录,但第9页显示11条记录。
有谁能帮我解决这个问题吗?

我认为LIMIT的第二个参数是数量,所以你可以只使用... LIMIT $start, 10,而不需要指定结束索引。如果出于某种原因需要一个结束索引,为什么不简单地使用$end = $start + 10呢? - xander
LIMIT语句中的第二个数字不是结束,而是您想要检索的记录数 - 因此这里应该始终为10。 - CD001
如果你只使用单个等号,那么你将会评估一个赋值而不是一个数学方程。因此,在这里你需要至少使用两个甚至三个等号。同样的情况也适用于 if($previous = 0) - lennyklb
我已经更新了我的答案,以照顾到所有这些。 - Andy
3个回答

2
你的问题来自于你不知道 LIMIT 关键字的工作原理。如果你只给它一个参数,它会被解释为必须返回的查询结果的最大条目数。如果你传递两个值,第一个将被解释为开始偏移量,而第二个仍然是返回条目的最大数量。
换句话说,在准备第5页时会发生写入 LIMIT 50, 60 的情况,这将从第51个匹配条目开始获取结果,并返回接下来的59个条目。
如果你想每页显示10条记录,请硬编码10作为第二个 LIMIT 参数,这样应该更好。 http://sql.sh/cours/limit

2

你最好考虑它是如何工作的原理,而不仅仅只看代码。

首先,你需要知道:

  • 表中有多少记录?你可以使用 COUNT() 来获取。
  • 每页显示多少条记录?你可以固定这个数字,比如说每页显示 10 条记录。

然后你需要了解 LIMIT 的工作原理。如果你执行类似于 LIMIT 50, 10 这样的语句,意味着从表中的第 51 条记录(注意索引从 0 开始)开始获取接下来的 10 行记录。后面的数字 10 是每页要显示的记录数。

在构建链接方面,最简单的方法是将 URL 中的 ?page= 参数设置为 LIMIT 查询中的第一个值,因为这个值会随着页面改变而改变(比如以上例子中的 50),而另一个数字(10)则是恒定的。你可以通过将表中记录的数量除以每页记录数并向上取整,得到适合 URL 的相应数字。

假设你的数据库中有 362 条记录,并且想每页显示 10 条记录,那么这将产生以下 URL:

$per_page = 10;
$records_in_db_table = 362; // You must calculate this from a COUNT() query
$n = ceil($records_in_db_table / $per_page);

for ($x=0; $x<$n; $x++) {
    $page = ($x * $per_page);
    echo '?page=' . $page;
}

以上代码输出:
?page=0
?page=10
?page=20
?page=30
// ...
?page=360

然后您只需将它们输入到查询的LIMIT条件中,例如:

  • ?page=10 == LIMIT 10, 10
  • ?page=20 == LIMIT 20, 10
  • ?page=30 == LIMIT 30, 10
  • 等等...

值得注意的是,您无需关心尝试将LIMIT限制为超过存在记录的数量会发生什么。例如,最后一个URL(?page=360)将执行LIMIT 360, 10。您的数据库中只有362条记录,因此您可能认为这不起作用,因为该查询只能返回2条记录。但是,它将仅返回最后2个记录,没有问题。

同样,如果您尝试使用远远超出总记录数的数字(?page=99999),它将仅返回一个空结果集,而不是错误。一些人编写简单的检查代码,例如:

if ((int)$_GET['page'] > $records_in_db_table) { 
    // Display error message
}

记住你应该对$_GET['page']进行过滤或者至少将其转换为整数。不要直接将任何来自$_GET的内容注入到你的查询中,如果可能的话,请使用参数绑定(例如PDO)。
你还可以查看DataTables (https://datatables.net/),因为它可以在不编写任何代码的情况下完成大部分需要做的事情,并且与Bootstrap兼容。

0
你应该忽略页面零,并尝试: 开始:($page - 1) * 10; 结束:$end = 10;

我认为保持这种方式是一个不好的主意。将该变量命名为end并使其为静态的在语义上是错误的。该变量本来就不应该首先被命名为$end,因为它是一个限制而不是偏移量。 - Sarkouille
@SanderBakker 没必要那么长,$limit 就足够清晰了 ;) 此外,该变量并不表示您将获得的记录数,而是查询后不返回记录的限制。 - Sarkouille
@SanderBakker,我已发布了一个答案,请看一下。可能会为您澄清其中的一些事情。 - Andy
如果您想了解如何集成分页,那应该是另一个问题的主题。 - Sarkouille
@ksjohn,我为你简化了。 - Mohamed Baddi
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接