StackOverflow Like Pagination
Some while ago, I built a pagination system in PHP to display a long list of pagination links. The pagination system showed at most 5 links at a time and additional links were represented by ellipsis (...). However, I was not able to deal with certain edge cases, so I drew some inspiration from the pagination system used on StackOverflow to tackle them. This is what the end result looked like:

- The first and last page links are always visible
- The previous and next page links (numeric ones) are always visible
- At most n page links excluding first and last page links are visible; rest are represented by ellipsis
- The pagination for first and last n - 1 pages is handled a bit differently
Complete PHP source code below.
DEMO DISINI
Pagination Function
<?php
/**
* Displays pagination links based on given parameters
*
* @param int $currentPage - current page
* @param int $itemCount - number of items to paginate, used to calculate total number of pages
* @param int $itemsPerPage - number of items per page, used to calculate total number of pages
* @param int $adjacentCount - half the number of page links displayed adjacent to the current page
* @param (string|callable) $pageLinkTemplate - pagination URL string containing %d placeholder or a callable function that accepts page number and returns page URL
* @param boolean $showPrevNext - whether to show previous and next page links
* @return void
*/
function pagination($currentPage, $itemCount, $itemsPerPage, $adjacentCount, $pageLinkTemplate, $showPrevNext = true) {
$firstPage = 1;
$lastPage = ceil($itemCount / $itemsPerPage);
if ($lastPage == 1) {
return;
}
if ($currentPage <= $adjacentCount + $adjacentCount) {
$firstAdjacentPage = $firstPage;
$lastAdjacentPage = min($firstPage + $adjacentCount + $adjacentCount, $lastPage);
} elseif ($currentPage > $lastPage - $adjacentCount - $adjacentCount) {
$lastAdjacentPage = $lastPage;
$firstAdjacentPage = $lastPage - $adjacentCount - $adjacentCount;
} else {
$firstAdjacentPage = $currentPage - $adjacentCount;
$lastAdjacentPage = $currentPage + $adjacentCount;
}
echo '<div>';
if ($showPrevNext) {
if ($currentPage == $firstPage) {
echo '<span><</span>';
} else {
echo '<a href="' . (is_callable($pageLinkTemplate) ? $pageLinkTemplate($currentPage - 1) : sprintf($pageLinkTemplate, $currentPage - 1)) . '"><</a>';
}
}
if ($firstAdjacentPage > $firstPage) {
echo '<a href="' . (is_callable($pageLinkTemplate) ? $pageLinkTemplate($firstPage) : sprintf($pageLinkTemplate, $firstPage)) . '">' . $firstPage . '</a>';
if ($firstAdjacentPage > $firstPage + 1) {
echo '<span>...</span>';
}
}
for ($i = $firstAdjacentPage; $i <= $lastAdjacentPage; $i++) {
if ($currentPage == $i) {
echo '<b>' . $i . '</b>';
} else {
echo '<a href="' . (is_callable($pageLinkTemplate) ? $pageLinkTemplate($i) : sprintf($pageLinkTemplate, $i)) . '">' . $i . '</a>';
}
}
if ($lastAdjacentPage < $lastPage) {
if ($lastAdjacentPage < $lastPage - 1) {
echo '<span>...</span>';
}
echo '<a href="' . (is_callable($pageLinkTemplate) ? $pageLinkTemplate($lastPage) : sprintf($pageLinkTemplate, $lastPage)) . '">' . $lastPage . '</a>';
}
if ($showPrevNext) {
if ($currentPage == $lastPage) {
echo '<span>></span>';
} else {
echo '<a href="' . (is_callable($pageLinkTemplate) ? $pageLinkTemplate($currentPage + 1) : sprintf($pageLinkTemplate, $currentPage + 1)) . '">></a>';
}
}
echo '</div>';
}
?>
Example 1
pagination(1, 123, 10, 2, "users.php?page=%d");
Example 2: Using canonical URL for first page
pagination(1, 123, 10, 2, function($page) {
// use a callback function to handle special cases e.g.
// return canonical URL for first page and page URL for rest
return $page == 1 ? "/users/" : "/users/$page/";
});
Komentar
Posting Komentar