【问题标题】:Pagination using MySQL LIMIT, OFFSET使用 MySQL LIMIT、OFFSET 进行分页
【发布时间】:2013-12-20 06:56:28
【问题描述】:

我有一些代码将数据限制为每页仅显示 4 个项目。我正在使用的列有大约 20-30 个项目,所以我需要将它们分散在页面中。

在第一页,我有:

    $result = mysqli_query($con,"SELECT * FROM menuitem LIMIT 4");
{
  echo "<tr>";
  echo "<td align='center'><img src=\"" . $row['picturepath'] . "\" /></td>";
  echo "<td align='center'>" . $row['name'] . "</td> <td align='center'> <input type='button' value='More Info'; onclick=\"window.location='more_info.php?';\"> </td>";
  echo "<td align='center'>" . $row['price'] . "</td> <td align='center'> <input type='button' value='Add to Order' onclick=''> </td>";
  echo "</tr>";
 }
echo "</table>";

mysqli_close($con);

    ?> 

    <table width="1024" align="center" >
        <tr height="50"></tr>
            <tr>
                <td width="80%" align="right">
                    <a href="itempage2.php">NEXT</a>
                </td>
                <td width="20%" align="right">
                    <a href="">MAIN MENU</a>
                </td>
            </tr>
    </table>

您会注意到页面底部的我的锚标记列出了第二个页面“itempage2.php”。在 item page 2 中,我有相同的代码,除了我的 select 语句列出了 4 的偏移量。

$result = mysqli_query($con,"SELECT * FROM menuitem LIMIT 4 offset 4");

当我的数据库中有预定数量的项目时,这是有效的。但这不是那么好。只有当有更多项目时,我才需要创建一个新页面,而不是像现在这样硬编码到其中。

如何创建多个页面而不必对每个新页面进行硬编码和偏移?

【问题讨论】:

  • 在顶部使用 $_GET。如果没有 $_GET,则偏移量为 0。限制可以硬编码为分页系统(例如,每页 10 个项目)

标签: php mysql limit offset


【解决方案1】:

首先,不要为每个页面设置单独的服务器脚本,这太疯狂了。大多数应用程序通过在 URL 中使用分页参数来实现分页。比如:

http://yoursite.com/itempage.php?page=2

您可以通过$_GET['page']访问请求的页码。

这使您的 SQL 公式变得非常简单:

// determine page number from $_GET
$page = 1;
if(!empty($_GET['page'])) {
    $page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT);
    if(false === $page) {
        $page = 1;
    }
}

// set the number of items to display per page
$items_per_page = 4;

// build query
$offset = ($page - 1) * $items_per_page;
$sql = "SELECT * FROM menuitem LIMIT " . $offset . "," . $items_per_page;

例如,如果这里的输入是page=2,每页有 4 行,那么您的查询将是“”

SELECT * FROM menuitem LIMIT 4,4

这就是分页的基本问题。现在,您需要了解总页数(以便您可以确定是否应显示“NEXT PAGE”或是否允许通过链接直接访问页面 X)。

为此,您必须了解表中的行数。

在尝试返回实际有限的记录集之前,您可以简单地通过 DB 调用来执行此操作(我说 BEFORE 是因为您显然想验证请求的页面是否存在)。

这其实很简单:

$sql = "SELECT your_primary_key_field FROM menuitem";
$result = mysqli_query($con, $sql);
$row_count = mysqli_num_rows($result);
// free the result set as you don't need it anymore
mysqli_free_result($result);

$page_count = 0;
if (0 === $row_count) {  
    // maybe show some error since there is nothing in your table
} else {
   // determine page_count
   $page_count = (int)ceil($row_count / $items_per_page);
   // double check that request page is in range
   if($page > $page_count) {
        // error to user, maybe set page to 1
        $page = 1;
   }
}

// make your LIMIT query here as shown above


// later when outputting page, you can simply work with $page and $page_count to output links
// for example
for ($i = 1; $i <= $page_count; $i++) {
   if ($i === $page) { // this is current page
       echo 'Page ' . $i . '<br>';
   } else { // show link to other page   
       echo '<a href="/menuitem.php?page=' . $i . '">Page ' . $i . '</a><br>';
   }
}

【讨论】:

  • 重用$sql变量会不会遇到麻烦?或者 "$row_count = mysqli_num_rows($result); // 释放结果集,因为你不再需要它 mysqli_free_result($result);"摆脱它?
  • @ClaaziX $sql 只是一个包含字符串的变量。您可以根据需要重用(或不重用)变量名。查询运行后与结果集的查询无关。例如,您可以更改mysqli_query 之后的行上的值,而不会对使用结果集产生任何影响。
  • 谢谢@MikeBrant。就一个问题。为什么我们在 $page 之后做 -1?你能向我解释一下吗,它甚至偏离了偏移量吗?我让你的脚本工作正常,但我仍然想知道 -1 如何使它正常工作......嗯,哈哈
  • @NiCkNewman 这是因为我假设您的页码以 1 开头(即 1、2、3 ...)。在确定要用于查询的偏移量时,您需要偏移量为 0 才能获得第一页。我从页码中减去 1 以获得从零开始的偏移量。假设您每页有 10 个项目,并且您想要第二页。对于第 2 页,此偏移量将像这样计算 -> $offset = (2 - 1) * 10 留给您的值为 10,这是您查询所需的偏移量。
  • 你救了我 :) 非常感谢分享
【解决方案2】:

使用OFFSET 时,十几页并不是什么大问题。但是当你有数百个页面时,你会发现OFFSET 对性能不利。这是因为每次都需要读取所有跳过的行。

最好remember where you left off

【讨论】:

    【解决方案3】:

    如果您想保持简单,请尝试一下。

    $page_number = mysqli_escape_string($con, $_GET['page']);
    $count_per_page = 20;
    $next_offset = $page_number * $count_per_page;
    $cat =mysqli_query($con, "SELECT * FROM categories LIMIT $count_per_page OFFSET $next_offset");
    while ($row = mysqli_fetch_array($cat))
            $count = $row[0];
    

    剩下的就看你自己了。 如果您有来自两个表的结果,我建议您尝试不同的方法。

    【讨论】:

      【解决方案4】:

      使用.. LIMIT :pageSize OFFSET :pageStart

      :pageStart 绑定到 the_page_index(即第一页为 0)* number_of_items_per_pages(例如 4),:pageSize 绑定到 number_of_items_per_pages。

      要检测“有更多页面”,请使用 SQL_CALC_FOUND_ROWS 或使用 .. LIMIT :pageSize OFFSET :pageStart + 1 并检测缺失的最后 (pageSize+1) 条记录。不用说,对于 index > 0 的页面,存在前一页。

      如果页面索引值嵌入在 URL 中(例如,在“上一页”和“下一页”链接中),则可以通过适当的 $_GET 项获得。

      【讨论】:

        猜你喜欢
        • 2020-12-30
        • 2011-09-12
        • 2020-03-05
        • 1970-01-01
        • 2012-10-06
        • 2015-07-24
        • 2020-08-19
        • 2013-06-24
        相关资源
        最近更新 更多