PHP: проблема с выводом ссылок пагинатора
Здравствуйте, товарищи!
У меня есть класс пагинации. И всё бы хорошо, но, при изминении количества выводимых на страницу элементов, сбиватеся вид блока пагинации (так себе, сформулировал). В общем, если задано выводить по одной строке из БД, то всё хорошо — 1 … 3 4 5 6 7 … 20, но, если более одной, то получается вот так — 1 … 3 4 5 6 7 … (т. е. не отображается последняя страница или первая, если текущая ближе к концу). В чём может быть проблема?
Вот сам класс:
class Pagination
{
private $max = INF; // 10
private $route;
private $index = '';
private $current_page;
private $total;
private $limit;
public function __construct($route, $total, $limit = 5) // 5
{
$this->route = $route;
$this->total = $total;
$this->limit = $limit;
$this->amount = $this->amount();
$this->setCurrentPage();
}
public function get()
{
$links = null;
$limits = $this->limits();
$html = '<ul>';
for ($this->amount = null, $page = $limits[0]; $page <= $limits[1]; $page++) {
if ($page == 1 or $page == $this->total or abs($page - $this->current_page) < 3) { // 3
if ($page == $this->current_page) {
$links .= $this->amount = '<li>' . $page . '</li>';
} else {
$links .= $this->amount = $this->generateHtml($page);
}
} else {
if ($this->amount == '<li>...</li>' or $this->amount == null) {
$links .= $this->amount = null;
} else {
$links .= $this->amount = '<li>...</li>';
}
}
}
$html .= $links . '</ul>';
return $html;
}
private function generateHtml($page, $text = null)
{
if (!$text) {
$text = $page;
}
if (strpos($_SERVER['REQUEST_URI'], 'admin') !== false) {
$prefix = 'admin/';
} else {
$prefix = null;
}
return '<li><a href="/' . $prefix . $this->route['controller'] . '/' . $this->route['action'] . '/' . $page . '">' . $text . '</a></li>';
}
private function limits()
{
$left = $this->current_page - round($this->max / 2); // 2
$start = $left > 0 ? $left : 1;
if ($start + $this->max <= $this->amount) {
$end = $start > 1 ? $start + $this->max : $this->max;
} else {
$end = $this->amount;
$start = $this->amount - $this->max > 0 ? $this->amount - $this->max : 1;
}
return array($start, $end);
}
private function setCurrentPage()
{
if (isset($this->route['page'])) {
$currentPage = $this->route['page'];
} else {
$currentPage = 1;
}
$this->current_page = $currentPage;
if ($this->current_page > 0) {
if ($this->current_page > $this->amount) {
$this->current_page = $this->amount;
}
} else {
$this->current_page = 1;
}
}
private function amount()
{
return ceil($this->total / $this->limit);
}
}
Ответы (1 шт):
Проблема в этой строке:
Нужно заменить либо на $page == $limits[1] или пересмотреть использование свойства amount
if ($page == 1 or $page == $this->total or abs($page - $this->current_page) < 3) { // 3
- Свойство
total, судя по конструктору, отвечает за общее количество записей, а не количество страниц страниц, поэтому условие$page == $this->totalвыполнится при условии одной записи на одной странице. - Свойство
indexне используется, зачем оно? - Конструктор занимается вычислением:
$this->amount = $this->amount();
И в единственном публичном методе эти значения затираются
$this->amount = null
- Вот это условие проверяется каждый раз при вызове, а зачем?
if (strpos($_SERVER['REQUEST_URI'], 'admin') !== false) {
$prefix = 'admin/';
}
Получилось незаконченное код-ревью, а ответ был в самом начале.
В результате получились следующие результаты:
Я установил $total = 140, $limit = 10. Все страницы сохраняются.
14 итераций:
| Итерация | Пагинация |
|---|---|
| #1: | 1 2 3 ... 14 |
| #2: | 1 2 3 4 ... 14 |
| #3: | 1 2 3 4 5 ... 14 |
| #4: | 1 2 3 4 5 6 ... 14 |
| #5: | 1 ... 3 4 5 6 7 ... 14 |
| #6: | 1 ... 4 5 6 7 8 ... 14 |
| #7: | 1 ... 5 6 7 8 9 ... 14 |
| #8: | 1 ... 6 7 8 9 10 ... 14 |
| #9: | 1 ... 7 8 9 10 11 ... 14 |
| #10: | 1 ... 8 9 10 11 12 ... 14 |
| #11: | 1 ... 9 10 11 12 13 14 |
| #12: | 1 ... 10 11 12 13 14 |
| #13: | 1 ... 11 12 13 14 |
| #14: | 1 ... 12 13 14 |