Разбиение на страницы с использованием MySQL LIMIT, OFFSET
У меня есть код, в котором данные LIMIT отображают только 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". На странице позиции 2 у меня есть тот же код, кроме того, что мой оператор select перечисляет смещение 4.
$result = mysqli_query($con,"SELECT * FROM menuitem LIMIT 4 offset 4");
Это работает, таким образом, когда в моей базе данных имеется определенное количество элементов. Но это не так хорошо. Мне нужно создать новую страницу только в том случае, если в ней больше элементов, а не жестко закодированных, как сейчас.
Как создать несколько страниц без необходимости жесткого кодирования каждой новой страницы и смещения?
Ответы
Ответ 1
Во-первых, у вас нет отдельного сервера script для каждой страницы, это просто безумие. Большинство приложений реализуют разбиение на страницы с использованием параметра 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
Итак, это основная проблема разбивки на страницы. Теперь у вас есть дополнительное требование, чтобы вы понимали общее количество страниц (чтобы вы могли определить, следует ли показывать "СЛЕДУЮЩАЯ СТРАНИЦА" или если вы хотите разрешить прямой доступ к странице X по ссылке).
Чтобы это сделать, вы должны понимать количество строк в таблице.
Вы можете просто сделать это с помощью вызова БД, прежде чем пытаться вернуть свой фактический ограниченный набор записей (я говорю, прежде чем вы, очевидно, хотите подтвердить, что запрошенная страница существует).
Это на самом деле довольно просто:
$sql = "SELECT your_primary_key_field FROM menuitem";
$result = mysqli_query($con, $sql);
if(false === $result) {
throw new Exception('Query failed with: ' . mysqli_error());
} else {
$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>';
}
}
Ответ 2
Используйте .. LIMIT :pageSize OFFSET :pageStart
Где :pageStart
привязано к_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) запись. Излишне говорить, что для страниц с индексом > 0 существует предыдущая страница.
Если значение индекса страницы вложено в URL-адрес (например, в ссылках "предыдущая страница" и "следующая страница" ), то его можно получить с помощью соответствующего элемента $_GET
.
Ответ 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];
Остальное зависит от вас.
Если у вас есть результат из двух таблиц, я предлагаю вам попробовать другой подход.