Skip to content

Pagination

Viames Marino edited this page Mar 26, 2026 · 2 revisions

Pair framework: Pagination

Pair\Html\Pagination renders page navigation and exposes SQL-friendly paging values.

It is usually created automatically by View, but it can also be used manually in scripts or custom UI flows.

Core properties

Pagination exposes its state mainly through magic properties:

  • page Current page, 1-based.
  • perPage Number of rows per page.
  • count Total number of rows available.
  • hideEmpty Whether to hide the bar when only one page exists.

Derived properties:

  • start SQL offset for the current page.
  • limit SQL limit for the current page.
  • pages Total number of pages.

Example:

$pagination = new \Pair\Html\Pagination();

// Current page coming from the router or another UI state source.
$pagination->page = 3;

// Number of rows to display per page.
$pagination->perPage = 20;

// Total rows available.
$pagination->count = 182;

// SQL-friendly values.
$start = $pagination->start; // 40
$limit = $pagination->limit; // 20
$pages = $pagination->pages; // 10

Main method

render(): string

This is the main method of the class.

It builds the pagination bar HTML using Router::getPageUrl(...) for every page link.

Current behavior:

  • returns an empty string when count is empty
  • returns an empty string when there is only one page and hideEmpty is true
  • shows a first-page arrow («) when the current page is greater than 1
  • shows a last-page arrow (») when the current page is lower than the last page
  • renders a sliding page window around the current page

Example:

$pagination = new \Pair\Html\Pagination();
$pagination->page = 3;
$pagination->perPage = 20;
$pagination->count = 182;

// Renders the HTML bar with links generated from Router::getPageUrl(...).
echo $pagination->render();

Practical MVC pattern

In normal Pair modules, View creates and injects the pagination object automatically:

protected function render(): void
{
    // Loads the current page of rows.
    $items = $this->model->getItems(\App\Orm\User::class);

    // Loads the full count for the pagination bar.
    $this->pagination->count = $this->model->countItems(\App\Orm\User::class);

    $this->assign('items', $items);
}

Then in the layout:

<?php if ($this->mustUsePagination($this->items)): ?>
    <?php // Renders the page navigation bar. ?>
    <?= $this->getPaginationBar() ?>
<?php endif; ?>

Manual usage outside a view

use Pair\Html\Pagination;

$pagination = new Pagination();

// Reads page state from the request or another source.
$pagination->page = max(1, (int)($_GET['page'] ?? 1));
$pagination->perPage = 25;
$pagination->count = 230;

// Uses the derived values in a custom SQL query.
$rows = \Pair\Orm\Database::load(
    'SELECT * FROM users ORDER BY id DESC LIMIT ' . $pagination->start . ', ' . $pagination->limit
);

Secondary details worth knowing

Although the class is small, these implementation details matter:

  • start is never negative; it is clamped to 0
  • pages is computed with ceil(count / perPage)
  • hideEmpty can be changed through magic assignment because __set() writes to the internal property

Example:

$pagination = new \Pair\Html\Pagination();
$pagination->page = 1;
$pagination->perPage = 20;
$pagination->count = 10;
$pagination->hideEmpty = false;

// Renders even if there is only one page.
echo $pagination->render();

Notes and caveats

  • The HTML output is tied to Router::getPageUrl(...), so route state and filters remain in sync automatically.
  • Pagination renders links only; it does not fetch data by itself.
  • If count is 0 or null, render() returns an empty string.

See also: Router, View, Model, Query, Database.

Clone this wiki locally