На самом деле достаточно четырех if-ов и одного цикла. Правда условия у этих if-ов довольно развесистые.
Сперва вычисляем какие номера страниц видны в начале, в конце и в середине
$start = 1 + $indent;
$end = $total - $indent;
$mid_start = $current - $indent;
$mid_end = $current + $indent;
Первый и последний if-else выводят активную или неактивную стрелочку ← →
(вместо неактивной, можно и вообще не выводить)
Цикл пробегает по всем страницам, проверяет не текущая ли это страница, или страница попадает в видимый диапазон, и нужно вывести кликабельную ссылку или троеточие.
лапша c кусками бутстрапаpublic static function renderPaginator($total, $current, $indent = 3)
{
$start = 1 + $indent;
$end = $total - $indent;
$mid_start = $current - $indent;
$mid_end = $current + $indent;
?>
<nav style="margin: 0 auto;">
<ul class="pagination">
<?
$skip1 = ($start > $current || $current > $end);
if ($current == 1) { // previous
?><li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">«</span></a></li><?
} else {
?><li><a href="?page=<?=($current-1)?>" aria-label="Previous"><span aria-hidden="true">«</span></a></li><?
}
for ($p = 1; $p <= $total; $p++) { // each page
if ($p == $current) {
?>
<li class="active"><a href="#"><?=$p?> <span class="sr-only">(текущая)</a></li><?
} else {
if($p < $start
|| ($p > $mid_start && $mid_end > $p)
|| ($p > $end)
|| ($p == $start && $p == $mid_start)
|| ($p == $end && $p == $mid_end)
) {
?>
<li><a href="?page=<?=$p?>"><?=$p?></a></li><?
} elseif($p == $start || $p == $end) {
?>
<li class="disabled"><a href="#">...</a></li><?
}
}
}
if ($current == $total) { // next
?><li class="disabled"><a href="#" aria-label="Next"><span aria-hidden="true">»</span></a></li><?
} else {
?><li><a href="?page=<?=($current-1)?>" aria-label="Next"><span aria-hidden="true">»</span></a></li><?
}
?>
</ul>
</nav>
<?
}