Еще во времена laravel 3 поступило мне задание от очередного оптимизатора, которое заключалось в следующем:
1. Постраничный вывод должен генерировать ссылки вида %%(t)/news/page2%%, %%(t)/news/page3%% и тд
2. Страницы %%(t)/news/page1%% не должно быть вообще, должно быть просто %%(t)/news%%
3. В %%(t)title%% нужно добавить номер страницы как-то так: "оригинальный тайтл" - страница "номер страницы"
4. Автоматическая генерация %%(t)link rel="canonical"%% для страниц с номером, добавление %%(t)link rel="prev"%% и %%(t)link rel="next"%%
Посмотрев исходники я понял что проще написать свой FPagination. F - потому что --fucking-- friendly.
Надежный как автомат Калашникова и простой как сатиновые трусы.
{{cut Собственно код:}}
%%
items = $items;
$this->currentPage = $currentPage;
$this->lastPage = $lastPage;
$this->pageName = $pageName;
$this->url = $url;
}
public function links()
{
if($this->lastPage > 1)
{
if($this->lastPage < 13)
{
$content = $this->getPageRange(1, $this->lastPage);
}
else
{
$content = $this->getPageSlider();
}
$pagination = '';
}
else
{
$pagination = '';
}
return $pagination;
}
public function getPageRange($start, $end)
{
$pages = '';
for($page = $start; $page <= $end; $page++)
{
if($this->currentPage == $page)
{
$pages .= $this->getActivePageWrapper($page);
}
else if($page == 1)
{
$pages .= $this->getBase($page);
}
else
{
$pages .= $this->getLink($page);
}
}
return $pages;
}
public function getActivePageWrapper($text)
{
return ''.$text.'';
}
public function getBase($page)
{
$link = ''.$page.'';
return $this->getPageLinkWrapper($link);
}
public function getPageLinkWrapper($link)
{
return '
';
}
public function getStart()
{
return $this->getPageRange(1, 2).$this->getDots();
}
public function getAdjacentRange()
{
return $this->getPageRange($this->currentPage - 3, $this->currentPage + 3);
}
public function getPreviousTouch($text = '« Предыдущая')
{
if($this->currentPage <= 1)
{
$link = ''.$text.'';
}
else
{
$link = ''.$text.'';
}
return $link;
}
public function prevUrl()
{
if($this->currentPage <= 2)
{
$url = $this->url;
}
else
{
$url = $this->url.'/'.$this->pageName.($this->currentPage - 1);
}
return $url;
}
public function getNextTouch($text = 'Следующая »')
{
if($this->currentPage >= $this->lastPage)
{
$link = ''.$text.'';
}
else
{
$link = ''.$text.'';
}
return $link;
}
public function nextUrl()
{
return $this->url.'/'.$this->pageName.($this->currentPage + 1);
}
public function getPrevious($text = '«')
{
if($this->currentPage <= 1)
{
return $this->getDisabledTextWrapper($text);
}
else
{
$link = ''.$text.'';
}
return $this->getPageLinkWrapper($link);
}
public function getDisabledTextWrapper($text)
{
return '
'.$text.'
';
}
public function getNext($text = '»')
{
if($this->currentPage >= $this->lastPage)
{
return $this->getDisabledTextWrapper($text);
}
$link = ''.$text.'';
return $this->getPageLinkWrapper($link);
}
public function getTitleAppend($text)
{
if($this->currentPage > 1)
{
$title = $text.' - страница '.$this->currentPage;
}
else
{
$title = $text;
}
return $title;
}
public function getSeoBlock()
{
$canonical = '';
$prev = '';
$next = '';
if($this->currentPage <= 1)
{
$content = $next;
}
else if($this->currentPage > 1 && $this->currentPage < $this->lastPage)
{
$content = $canonical.$prev.$next;
}
else
{
$content = $canonical.$prev;
}
return $content;
}
}
%%
Данная реализация заточена под ((http://bulma.io/ Bulma framework)) но поменять классы на верстку Bootstrap или любую другую не сложно.
Как этим чудом пользоваться в Laravel?
Я делаю так:
Создаю функцию помощника, даже две
%%
//resources/helpers.php
count();
$lastPage = ceil($total / $perPage);
if($currentPage > $lastPage)
{
abort(404);
}
else
{
$items = $sql->skip(($currentPage * $perPage) - $perPage)
->take($perPage)
->get();
$routeParameters = array_values(\Route::current()
->parameters());
$count = count($routeParameters);
if($count >= 1)
{
if(starts_with($routeParameters[$count - 1], $pageName))
{
unset($routeParameters[$count - 1]);
}
}
$url = action($action, $routeParameters);
return new \App\Classes\FPagination($items, $currentPage, $lastPage, $perPage, $pageName, $url);
}
}
%%
Еще нужно добавить scope в модель. Можно сделать глобальный, но я предпочитаю локальные, на случай дополнительных доработок. Можно и без него, это скорее для красоты.
%%
news = \App\Models\News::pagination($currentPage, 30);
return $view;
}
}
%%
Если метод контроллера принимает больше одного параметра, $currentPage = null должен быть последним.
В представлении 'news/index'
%%
@extends('base/page')
@section('meta')
{{ $users->getSeoBlock() }}
@endsection
@section('title')
{{ $users->getTitleAppend('Новости') }}
@endsection
@section('content')
@foreach($news->items as $item)
@endforeach
{{ $news->links() }}
@endsection
%%
Данный класс удобно тягать с собой из проекта в проект, довольно просто настраивается под любую верстку, если почесать репу можно прикрутить и к другим фреймворкам или формировать им постраничный вывод для массивов\коллекций. --Composter-- Composer пакет собирать лениво, мне проще так - как в старое доброе время.
Навеяно ((768 этим)).