Here is some code based on original code from this very old link. It uses markup compatible with Bootstrap’s pagination component, and outputs page links like this:
[1] 2 3 4 5 6 ... 100
1 [2] 3 4 5 6 ... 100
...
1 2 ... 14 15 [16] 17 18 ... 100
...
1 2 ... 97 [98] 99 100
<?php
// How many adjacent pages should be shown on each side?
$adjacents = 3;
//how many items to show per page
$limit = 5;
// if no page var is given, default to 1.
$page = (int)$_GET["page"] ?? 1;
//first item to display on this page
$start = ($page - 1) * $limit;
/* Get data. */
$data = $db
->query("SELECT * FROM mytable LIMIT $start, $limit")
->fetchAll();
$total_pages = count($data);
/* Setup page vars for display. */
$prev = $page - 1;
$next = $page + 1;
$lastpage = ceil($total_pages / $limit);
//last page minus 1
$lpm1 = $lastpage - 1;
$first_pages = "<li class="page-item"><a class="page-link" href="https://stackoverflow.com/questions/163809/?page=1">1</a></li>" .
"<li class="page-item"><a class="page-link" href="?page=2">2</a>";
$ellipsis = "<li class="page-item disabled"><span class="page-link">...</span></li>";
$last_pages = "<li class="page-item"><a class="page-link" href="?page=$lpm1">$lpm1</a></li>" .
"<li class="page-item"><a class="page-link" href="?page=$lastpage">$lastpage</a>";
$pagination = "<nav aria-label="page navigation">";
$pagincation .= "<ul class="pagination">";
//previous button
$disabled = ($page === 1) ? "disabled" : "";
$pagination.= "<li class="page-item $disabled"><a class="page-link" href="?page=$prev">« previous</a></li>";
//pages
//not enough pages to bother breaking it up
if ($lastpage < 7 + ($adjacents * 2)) {
for ($i = 1; $i <= $lastpage; $i++) {
$active = $i === $page ? "active" : "";
$pagination .= "<li class="page-item $active"><a class="page-link" href="?page=$i">$i</a></li>";
}
} elseif($lastpage > 5 + ($adjacents * 2)) {
//enough pages to hide some
//close to beginning; only hide later pages
if($page < 1 + ($adjacents * 2)) {
for ($i = 1; $i < 4 + ($adjacents * 2); $i++) {
$active = $i === $page ? "active" : "";
$pagination .= "<li class="page-item $active"><a class="page-link" href="?page=$i">$i</a></li>";
}
$pagination .= $ellipsis;
$pagination .= $last_pages;
} elseif($lastpage - ($adjacents * 2) > $page && $page > ($adjacents * 2)) {
//in middle; hide some front and some back
$pagination .= $first_pages;
$pagination .= $ellipsis
for ($i = $page - $adjacents; $i <= $page + $adjacents; $i++) {
$active = $i === $page ? "active" : "";
$pagination .= "<li class="page-item $active"><a class="page-link" href="?page=$i">$i</a></li>";
}
$pagination .= $ellipsis;
$pagination .= $last_pages;
} else {
//close to end; only hide early pages
$pagination .= $first_pages;
$pagination .= $ellipsis;
$pagination .= "<li class="page-item disabled"><span class="page-link">...</span></li>";
for ($i = $lastpage - (2 + ($adjacents * 2)); $i <= $lastpage; $i++) {
$active = $i === $page ? "active" : "";
$pagination .= "<li class="page-item $active"><a class="page-link" href="?page=$i">$i</a></li>";
}
}
}
//next button
$disabled = ($page === $last) ? "disabled" : "";
$pagination.= "<li class="page-item $disabled"><a class="page-link" href="?page=$next">next »</a></li>";
$pagination .= "</ul></nav>";
if($lastpage <= 1) {
$pagination = "";
}
echo $pagination;
foreach ($data as $row) {
// display your data
}
echo $pagination;