Skip to content

📖 Pagination ​

Pagination in version 3 is illuminate/pagination. There is no PageBlocks Paginator class any more — paginate() returns a standard Illuminate\Pagination\LengthAwarePaginator.

Most of the time you want pbList

pbList already wires up a paginated list, including the AJAX part, without a controller. Reach for the paginator directly only when you are writing a controller of your own.

Paginating a query ​

Works the same on the query builder and on a model:

php
$paginator = query('site_content')
    ->where('template', 5)
    ->whereNotNull('publishedon')
    ->orderByDesc('publishedon')
    ->paginate(5);

$paginator = model('PbResource')->published()->paginate(10);

The current page is taken from the page query parameter.

What the paginator gives you ​

php
$paginator->items();        // array of rows on this page
$paginator->total();        // 92  - rows in total
$paginator->currentPage();  // 1
$paginator->lastPage();     // 19
$paginator->perPage();
$paginator->hasPages();
$paginator->links();        // rendered navigation

links() returns ready HTML. Which markup you get is a template name, and the shipped default is pages:

NameMarkup
pagesthe default — Bootstrap pagination, numbers with « / »
bootstrapBootstrap with worded "newer / older" captions and Bootstrap Icons arrows
tailwindTailwind utility classes
simplebare <a> inside .pagination, no framework
php
$paginator->links();            // 'pages'
$paginator->links('tailwind');

The captions are not translated

They are hard-coded in the renderer, not read from a lexicon, and some of them are Russian. The renderer is yours — it lives in core/App/Services/PaginationViewFactory.php, which the package writes once and never overwrites again. Edit it, or render the navigation from $paginator->items() and the page numbers yourself.

PaginationViewFactory::setDefaultTemplate('simple') changes the default for the whole site.

Keeping the query string ​

By default the page links carry only ?page=N and drop everything else — filters included. withQueryString() keeps the rest:

php
$paginator = query('site_content')->paginate(10)->withQueryString();

This is a common source of "the filter resets when I go to page 2".

Two neighbours, for when withQueryString() is too much or not enough:

php
$paginator->appends(['sort' => 'price']);  // add your own parameters
$paginator->fragment('list');              // every link ends in #list

In a template ​

php
{foreach $paginator->items() as $item}
    <article>
        <a href="{$item->uri}">{$item->pagetitle}</a>
    </article>
{/foreach}

<nav>{$paginator->links()}</nav>

A controller example ​

php
class NewsController
{
    public function index()
    {
        $paginator = query('site_content')
            ->where('template', 5)
            ->orderByDesc('publishedon')
            ->paginate(5)
            ->withQueryString();

        return view('file:templates/news', [
            'paginator' => $paginator,
        ]);
    }
}

AJAX ​

The paginator itself renders plain links. If you want page changes without a reload, either use pbList — it stores the query server-side under an opaque key and swaps the rows over AJAX — or drive the links yourself with pbPagination.

© PageBlocks 2019-present