Skip to main content
Version: 5.x

Pagination

Introduction​

Pagination is an essential feature for displaying large amounts of data in an organized way. BowPHP provides a powerful and flexible Pagination class that makes it easy to navigate through database query results.

Basic usage​

paginate signature​

paginate(int $per_page, int $current = 0, ?int $chunk = null): Pagination
ParameterTypeDescription
per_pageintNumber of items per page.
currentintRequested page number (1-indexed). 0 is normalized to 1.
chunk?intIf set, the returned collection is split into sub-arrays of this size.

Pagination with the Query Builder​

You can paginate Query Builder results using the paginate method:

use Bow\Database\Database;

$users = Database::table('users')->paginate(15);

// Specific page
$users = Database::table('users')->paginate(15, $request->get('page', 1));

Pagination with models​

With the Barry ORM, pagination is just as simple:

use App\Models\User;

$users = User::paginate(15);
$users = User::paginate(15, 2); // Page 2

Pagination with conditions​

You can combine pagination with query conditions:

use App\Models\User;

$users = User::where('status', 'active')
->orderBy('created_at', 'desc')
->paginate(10);

The Pagination class provides several methods for navigating between pages:

Information about the current page​

use App\Models\User;

$pagination = User::paginate(15);

// Get the current page number
$pagination->current(); // e.g. 2

// Get the number of items per page
$pagination->perPage(); // e.g. 15

// Get the total number of items
$pagination->total(); // e.g. 150

// Get the total number of pages
$pagination->totalPages(); // e.g. 10
// Get the next page number (0 on the last page)
$pagination->next(); // e.g. 3

// Check whether there is a next page
$pagination->hasNext(); // true or false

// Get the previous page number
$pagination->previous(); // e.g. 1

// Check whether there is a previous page
$pagination->hasPrevious(); // true or false
Caveat about hasPrevious() on the first page

On page 1, previous() returns 1 (not 0), which means that hasPrevious() returns true β€” it only signals that a "previous" page number is available, not that there is actually a page before the current one.

To decide whether to display a "Previous" link in a view, prefer onFirstPage():

if (!$pagination->onFirstPage()) {
// Display the Previous link
}

The same logic applies on the right side: hasNext() is reliable, but onLastPage() is often more expressive in a template.

Position checks​

// Check whether we are on the first page
$pagination->onFirstPage(); // true or false

// Check whether we are on the last page
$pagination->onLastPage(); // true or false

// Check whether there are multiple pages
$pagination->hasPages(); // true or false

Accessing the data​

Retrieving items​

// Get the collection of items for the current page
$items = $pagination->items();

foreach ($items as $item) {
echo $item->name;
}

Information about the items​

// Number of items on the current page
$pagination->count(); // e.g. 15

// Check whether the pagination is empty
$pagination->isEmpty(); // true or false

// Check whether the pagination contains items
$pagination->isNotEmpty(); // true or false

// Index of the first item (1-indexed)
$pagination->firstItem(); // e.g. 16 (on page 2 with 15 per page)

// Index of the last item (1-indexed)
$pagination->lastItem(); // e.g. 30

Array access​

The Pagination class implements ArrayAccess, which lets you access items like an array:

// Access an item by its index
$firstUser = $pagination[0];

// Check whether an index exists
if (isset($pagination[0])) {
// ...
}

Iteration​

You can iterate directly over the pagination object:

foreach ($pagination as $user) {
echo $user->name;
}

Generating URLs​

The Pagination class can generate URLs for navigation.

Configuring the base URL​

$pagination->setBaseUrl('https://example.com/users');

Customizing the page parameter​

By default, the page parameter is page. You can customize it:

$pagination->setPageParam('p');
// Will generate URLs like: https://example.com/users?p=2

Adding query parameters​

// Add parameters (keeps existing ones)
$pagination->withQueryParams(['sort' => 'name', 'order' => 'asc']);

// Replace all parameters
$pagination->setQueryParams(['filter' => 'active']);

Reading the current configuration​

Three getters let you retrieve the current URL configuration β€” useful for debugging or to read the configuration back in a shared view:

$pagination->getBaseUrl();      // 'https://example.com/users' or null
$pagination->getPageParam(); // 'page' (or the value set via setPageParam)
$pagination->getQueryParams(); // ['sort' => 'name', 'order' => 'asc']

Generating URLs​

// URL for a specific page
$pagination->url(3); // https://example.com/users?page=3

// URL of the next page
$pagination->nextPageUrl(); // https://example.com/users?page=3

// URL of the previous page
$pagination->previousPageUrl(); // https://example.com/users?page=1

// URL of the first page
$pagination->firstPageUrl(); // https://example.com/users?page=1

// URL of the last page
$pagination->lastPageUrl(); // https://example.com/users?page=10

URL range​

You can obtain an array of URLs for a range of pages around the current page:

// Get the URLs for 3 pages on each side of the current page
$urls = $pagination->getUrlRange(3);
// [
// 2 => 'https://example.com/users?page=2',
// 3 => 'https://example.com/users?page=3',
// 4 => 'https://example.com/users?page=4', // current page
// 5 => 'https://example.com/users?page=5',
// 6 => 'https://example.com/users?page=6',
// ]

The links() method generates a complete array of data for rendering the pagination:

$links = $pagination->links(2); // 2 pages on each side

Each element of the array contains:

  • url: The page URL (or null)
  • label: The text to display
  • active: Whether it is the current page
  • disabled: Whether the link is disabled

Example result​

[
['url' => 'https://...?page=1', 'label' => 'Β« Previous', 'active' => false, 'disabled' => false],
['url' => 'https://...?page=1', 'label' => '1', 'active' => false, 'disabled' => false],
['url' => null, 'label' => '...', 'active' => false, 'disabled' => true],
['url' => 'https://...?page=4', 'label' => '4', 'active' => false, 'disabled' => false],
['url' => 'https://...?page=5', 'label' => '5', 'active' => true, 'disabled' => false],
['url' => 'https://...?page=6', 'label' => '6', 'active' => false, 'disabled' => false],
['url' => null, 'label' => '...', 'active' => false, 'disabled' => true],
['url' => 'https://...?page=10', 'label' => '10', 'active' => false, 'disabled' => false],
['url' => 'https://...?page=6', 'label' => 'Next Β»', 'active' => false, 'disabled' => false],
]

Serialization​

Converting to an array​

$array = $pagination->toArray();
// [
// 'current_page' => 2,
// 'data' => [...],
// 'first_item' => 16,
// 'last_item' => 30,
// 'per_page' => 15,
// 'total' => 150,
// 'total_pages' => 10,
// 'next_page' => 3,
// 'previous_page' => 1,
// ]

Converting to JSON​

$json = $pagination->toJson();

// With formatting options
$json = $pagination->toJson(JSON_PRETTY_PRINT);

Displaying in views​

With Tintin (template engine)​

<div class="container">
<!-- Display the items -->
%foreach($users as $user)
<div class="user">
{{ $user->name }}
</div>
%endforeach

<!-- Pagination navigation -->
%if($users->hasPages())
<nav class="pagination">
<!-- Previous button (we use onFirstPage to avoid a link to
the current page: hasPrevious() stays true on page 1, see Note above). -->
%if(!$users->onFirstPage())
<a href="{{ $users->previousPageUrl() }}">Β« Previous</a>
%else
<span class="disabled">Β« Previous</span>
%endif

<!-- Page links -->
%foreach($users->links() as $link)
%if($link['disabled'])
<span class="disabled">{{ $link['label'] }}</span>
%elseif($link['active'])
<span class="active">{{ $link['label'] }}</span>
%else
<a href="{{ $link['url'] }}">{{ $link['label'] }}</a>
%endif
%endforeach

<!-- Next button -->
%if(!$users->onLastPage())
<a href="{{ $users->nextPageUrl() }}">Next Β»</a>
%else
<span class="disabled">Next Β»</span>
%endif
</nav>
%endif
</div>

Pagination information​

<p>
Showing {{ $users->firstItem() }} to {{ $users->lastItem() }}
of {{ $users->total() }} results
</p>

Complete example​

Controller​

namespace App\Http\Controllers;

use App\Models\User;
use Bow\Http\Request;

class UserController
{
public function index(Request $request)
{
$perPage = $request->get('per_page', 15);
$search = $request->get('search');

$query = User::query();

if ($search) {
$query->where('name', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%");
}

$users = $query->orderBy('name')->paginate($perPage);

// Configure the pagination URLs
$users->setBaseUrl(url('/users'))
->withQueryParams([
'search' => $search,
'per_page' => $perPage,
]);

return view('users.index', compact('users', 'search'));
}
}

Route​

$app->get('/users', 'UserController::index');

Is something missing?

If you run into problems with the documentation or have suggestions to improve the documentation or the project in general, please open an issue for us, or send a tweet mentioning the Twitter account @bowframework or directly on github.