Customizing Laravel Pagination for Pseudo‑Static URLs
This guide explains how to override Laravel's built‑in pagination component to generate clean pseudo‑static URLs by creating a custom LengthAwarePaginator, rewriting its url method, and providing a staticPaginate scope for selective use.
In a Laravel project the built‑in pagination component generates URLs with query parameters, which does not satisfy the requirement for pseudo‑static URLs such as /software/3dmax/created_at/page-1.html.
The desired routing pattern is /software/{category}/{order}/page-{page}.html, but the default paginator produces URLs like
/software/3dmax/created_at/page-1.html?category=3dmax&order=created_at&page=2.
To achieve the required format we need to override the Laravel paginator. First create a custom paginator class that extends Illuminate\Pagination\LengthAwarePaginator:
mkdir app/Pagination
touch app/Pagination/LengthAwarePaginator.phpFile app/Pagination/LengthAwarePaginator.php:
<?php
namespace App\Pagination;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Pagination\LengthAwarePaginator as BasePaginator;
class LengthAwarePaginator extends BasePaginator
{
}Then rewrite the url method to move route parameters from the query string into the path while preserving other query parameters:
public function url($page)
{
if ($page <= 0) {
$page = 1;
}
$parameters = [$this->pageName => $page];
if (count($this->query) > 0) {
$parameters = array_merge($this->query, $parameters);
}
// parameters bound to the route
$params = \request()->route()->parameters();
if (!empty($params)) {
foreach ($parameters as $key => $parameter) {
if (isset($params[$key])) {
$params[$key] = $parameter;
unset($parameters[$key]);
}
}
$path = route(\request()->route()->getAction('as'), $params);
} else {
$path = $this->path;
}
// if no remaining query parameters
if (empty(Arr::query($parameters))) {
return $path . $this->buildFragment();
}
return $path
. (Str::contains($this->path, '?') ? '&' : '?')
. Arr::query($parameters)
. $this->buildFragment();
}Next, replace the default paginator with the custom one in the application’s service container:
# replace
use App\Pagination\LengthAwarePaginator;
# --- use Illuminate\Contracts\Pagination\LengthAwarePaginator; // commented
...
/**
* @param \Illuminate\Support\Collection $items
* @param int $total
* @param int $perPage
* @param int $currentPage
* @param array $options
* @return LengthAwarePaginator
*/
protected function paginator($items, $total, $perPage, $currentPage, $options)
{
return Container::getInstance()->makeWith(LengthAwarePaginator::class, compact(
'items', 'total', 'perPage', 'currentPage', 'options'
));
}For cases where only some pages need pseudo‑static URLs, define a local scope staticPaginate in a base model class:
public function scopeStaticPaginate($builder, $perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
{
if (request('page')) {
request()->offsetSet('page', request('page'));
}
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$perPage = $perPage ?: $builder->getModel()->getPerPage();
$results = ($total = $builder->toBase()->getCountForPagination())
? $builder->forPage($page, $perPage)->get($columns)
: $builder->getModel()->newCollection();
return $this->paginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
}Finally, use the custom paginator in code:
Model::query()->staticPaginate($pageSize);By following these steps the Laravel application will generate clean pseudo‑static pagination URLs while still supporting normal query‑based pagination where needed.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
php Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
