Рассчет отступов в пагинации?
На самом деле достаточно четырех 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">&laquo;</span></a></li><?
            } else {
                ?><li><a href="?page=<?=($current-1)?>" aria-label="Previous"><span aria-hidden="true">&laquo;</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">&raquo;</span></a></li><?
            } else {
                ?><li><a href="?page=<?=($current-1)?>" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li><?
            }
            ?>
  
        </ul>
    </nav>    
    <?
    }
Контроллер
if (isset($_GET['page'])) {
			$page = $_GET['page'];
		} else {
			$page = 1;
		}
        $dataitems = array(
			'start' => ($page - 1) * 20,
			'limit' => 20
		);
Модель
		$sql = "SELECT * FROM table order by `id`";
		if (isset($dataitems['start']) || isset($dataitems['limit'])) {
			if ($dataitems['start'] < 0) {
				$dataitems['start'] = 0;
			}
			if ($dataitems['limit'] < 1) {
				$dataitems['limit'] = 20;
			}
			$sql .= " LIMIT " . (int)$dataitems['start'] . "," . (int)$dataitems['limit'];
		}