Laravel 5.5 ЧПУ ссылка в пагинации
Как я сделал средствами Laravel красивые ссылки при пагинации.
История началась с того, что на просторах русско-язычного интернета я не смог найти рабочую схему создания средствами самого Laravel красивые ссылки при пагинации. В английском не силён, но всё таки с переводчиком кое как смог преодолеть этот казалось бы простой шаг.
Странно, что такая казалось бы актуальная ситуация не реализована в таком мощном фреймворке, как Laravel на более доступном уровне.
Собственно к делу.
Такая была задача: сайт старый, в нем много ссылок такого вида:
http://site/section/russia/page-6.html
Но по умолчанию Laravel прописывает адреса так
http://site/section/russia.html?page=6
что меня не устраивало.
Первое что я сделал - прописал маршрут таким образом
Route::get('/section/{region}/page-{page}.html', 'SiteSectionController@show')
Вроде бы все ок, переменная page есть, но Laravel не подхватывал ее, а использовал свою.
Далее, в контроллере я заменяю стандартную конструкцию пагинатора
->paginate(10);
на вот такую
->paginate(10, ['*'], 'page', $page);
Здесь я явно указываю пагинатору работать с моей пользовательской переменной page вместо его стандартной зашитой глубоко в кишках фреймворка.
Собственно на этом этапе Laravel прекрасно понимает ссылки вида
http://site/section/russia/page-6.html
что мне собственно и нужно было.
Но все равно в конце ссылки он подставляет свои ненавистные мне
?page=6
Что бы исправить это недоразумение я делал вот что. Это чисто мое представление, возможно оно и не стыкуется с философией Laravela, но на данном этапе ничего лучшего я не придумал и не нашел.
Следующий этап, с помощью консоли и вот такой команды
php artisan vendor:publish --tag=laravel-pagination
переместил стандартные шалоны пагинации Laravel в директорию
resources/views/vendor/pagination
Теперь шаблон доступен для свободного редактирования. В папке 4 файла, нужный мне называется
default.blade.php
Привожу мой отредактированный вид шаблона пагинатора, все изменения подчеркнуты
@php
$pattern = ['~/page-d+.html?page=d+~', '~.html?page=d+~'];
@endphp
@if ($paginator->hasPages())
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="disabled"><span>«</span></li>
@else
@if ($paginator->currentPage() == 2)
<li><a href="{{ preg_replace($pattern, '', $paginator->previousPageUrl()) }}.html" rel="prev">«</a></li>
@else
<li><a href="{{ preg_replace($pattern, '/page-'.($paginator->currentPage()-1), $paginator->previousPageUrl()) }}.html" rel="prev">«</a></li>
@endif
@endif
{{-- Pagination Elements --}}
@foreach ($elements as $element)
{{-- "Three Dots" Separator --}}
@if (is_string($element))
<li class="disabled"><span>{{ $element }}</span></li>
@endif
{{-- Array Of Links --}}
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<li class="active"><span>{{ $page }}</span></li>
@else
@if ($page == 1)
<li><a href="{{ preg_replace($pattern, '', $url) }}.html">{{ $page }}</a></li>
@else
<li><a href="{{ preg_replace($pattern, '/page-'.$page, $url) }}.html">{{ $page }}</a></li>
@endif
@endif
@endforeach
@endif
@endforeach
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li><a href="{{ preg_replace($pattern, '/page-'.($paginator->currentPage()+1), $paginator->nextPageUrl()) }}.html" rel="next">»</a></li>
@else
<li class="disabled"><span>»</span></li>
@endif
</ul>
@endif
Если сравнить этот файл с оригиналом легко можно понять суть переделки.
С помощью регулярок я просто вычистил все мне мешающее в ссылках, а со страницы номер 1 удалил page совсем. Здесь ничего сложного, есть только php код, но его одна строка, где простой массив с паттернами. Можно конечно было передать его в параметрах вот таким образом
{{ $posts->links('vendor.pagination.default', ['pattern' => $pattern]) }}
Но я посчитал это несущественным.
Повторюсь, это мой путь, скорее всего он не совсем верный. Возможно есть более элегантное решение, если кто знает поделитесь, буду очень признателен.
А если кому-то поможет, значит не зря пост кропал.
Всем удачи.
Костыльненько, но в инете другого варианта не нахожу