class Cake\View\Helper\PaginatorHelper(View $view, array $config = [])

The PaginatorHelper is used to output pagination controls such as page numbers and next/previous links. It works in tandem with PaginatorComponent.

See also Pagination for information on how to create paginated datasets and do paginated queries.

PaginatorHelper Templates

Internally PaginatorHelper uses a series of simple HTML templates to generate markup. You can modify these templates to customize the HTML generated by the PaginatorHelper.

Templates use {{var}} style placeholders. It is important to not add any spaces around the {{}} or the replacements will not work.

Loading Templates from a File

When adding the PaginatorHelper in your controller, you can define the ‘templates’ setting to define a template file to load. This allows you to customize multiple templates and keep your code DRY:

// In your AppView.php
public function initialize()
    $this->loadHelper('Paginator', ['templates' => 'paginator-templates']);

This will load the file located at config/paginator-templates.php. See the example below for how the file should look like. You can also load templates from a plugin using plugin syntax:

// In your AppView.php
public function initialize()
    $this->loadHelper('Paginator', ['templates' => 'MyPlugin.paginator-templates']);

Whether your templates are in the primary application or a plugin, your templates file should look something like:

return [
    'number' => '<a href="{{url}}">{{text}}</a>',

Changing Templates at Run-time


This method allows you to change the templates used by PaginatorHelper at runtime. This can be useful when you want to customize templates for a particular method call:

// Read the current template value.
$result = $this->Paginator->getTemplates('number');
// Prior to 3.4
$result = $this->Paginator->templates('number');

// Change a template
    'number' => '<em><a href="{{url}}">{{text}}</a></em>'


Template strings containing a percentage sign (%) need special attention, you should prefix this character with another percentage so it looks like %%. The reason is that internally templates are compiled to be used with sprintf(). Example: ‘<div style=”width:{{size}}%%”>{{content}}</div>’

Template Names

PaginatorHelper uses the following templates:

  • nextActive The active state for a link generated by next().

  • nextDisabled The disabled state for next().

  • prevActive The active state for a link generated by prev().

  • prevDisabled The disabled state for prev()

  • counterRange The template counter() uses when format == range.

  • counterPages The template counter() uses when format == pages.

  • first The template used for a link generated by first().

  • last The template used for a link generated by last()

  • number The template used for a link generated by numbers().

  • current The template used for the current page.

  • ellipsis The template used for ellipses generated by numbers().

  • sort The template for a sort link with no direction.

  • sortAsc The template for a sort link with an ascending direction.

  • sortDesc The template for a sort link with a descending direction.

Checking the Pagination State

Cake\View\Helper\PaginatorHelper::current(string $model = null)

Gets the current page of the recordset for the given model:

// Our URL is:
echo $this->Paginator->current('Comment');
// Output is 3
Cake\View\Helper\PaginatorHelper::hasNext(string $model = null)

Returns true if the given result set is not at the last page.

Cake\View\Helper\PaginatorHelper::hasPrev(string $model = null)

Returns true if the given result set is not at the first page.

Cake\View\Helper\PaginatorHelper::hasPage(string $model = null, integer $page = 1)

Returns true if the given result set has the page number given by $page.

Cake\View\Helper\PaginatorHelper::total(string $model = null)

Returns the total number of pages for the provided model.

New in version 3.4.0.

Creating a Page Counter

Cake\View\Helper\PaginatorHelper::counter($options = [])

Returns a counter string for the paged result set. Using a provided format string and a number of options you can create localized and application specific indicators of where a user is in the paged data set.

There are a number of options for counter(). The supported ones are:

  • format Format of the counter. Supported formats are ‘range’, ‘pages’ and custom. Defaults to pages which would output like ‘1 of 10’. In the custom mode the supplied string is parsed and tokens are replaced with actual values. The available tokens are:

    • {{page}} - the current page displayed.

    • {{pages}} - total number of pages.

    • {{current}} - current number of records being shown.

    • {{count}} - the total number of records in the result set.

    • {{start}} - number of the first record being displayed.

    • {{end}} - number of the last record being displayed.

    • {{model}} - The pluralized human form of the model name. If your model was ‘RecipePage’, {{model}} would be ‘recipe pages’.

    You could also supply only a string to the counter method using the tokens available. For example:

    echo $this->Paginator->counter(
        'Page {{page}} of {{pages}}, showing {{current}} records out of
         {{count}} total, starting on record {{start}}, ending on {{end}}'

    Setting ‘format’ to range would output like ‘1 - 3 of 13’:

    echo $this->Paginator->counter([
        'format' => 'range'
  • model The name of the model being paginated, defaults to PaginatorHelper::defaultModel(). This is used in conjunction with the custom string on ‘format’ option.

Generating Pagination URLs

Cake\View\Helper\PaginatorHelper::generateUrl(array $options = [], $model = null, $full = false)

By default returns a full pagination URL string for use in non-standard contexts (i.e. JavaScript).

echo $this->Paginator->generateUrl(['sort' => 'title']);

Creating a Limit Selectbox Control

Cake\View\Helper\PaginatorHelper::limitControl(array $limits = [], $default = null, array $options = [])

Create a dropdown control that changes the limit query parameter:

// Use the defaults.
echo $this->Paginator->limitControl();

// Define which limit options you want.
echo $this->Paginator->limitControl([25 => 25, 50 => 50]);

// Custom limits and set the selected option
echo $this->Paginator->limitControl([25 => 25, 50 => 50], $user->perPage);

The generated form and control will automatically submit on change.

New in version 3.5.0: The limitControl() method was added in 3.5.0

Configuring Pagination Options

Cake\View\Helper\PaginatorHelper::options($options = [])

Sets all the options for the PaginatorHelper. Supported options are:

  • url The URL of the paginating action. ‘url’ has a few sub options as well:

    • sort The key that the records are sorted by.

    • direction The direction of the sorting. Defaults to ‘ASC’.

    • page The page number to display.

    The above mentioned options can be used to force particular pages/directions. You can also append additional URL content into all URLs generated in the helper:

        'url' => [
            'sort' => 'email',
            'direction' => 'desc',
            'page' => 6,
            'lang' => 'en'

    The above adds the en route parameter to all links the helper will generate. It will also create links with specific sort, direction and page values. By default PaginatorHelper will merge in all of the current passed arguments and query string parameters.

  • escape Defines if the title field for links should be HTML escaped. Defaults to true.

  • model The name of the model being paginated, defaults to PaginatorHelper::defaultModel().

Example Usage

It’s up to you to decide how to show records to the user, but most often this will be done inside HTML tables. The examples below assume a tabular layout, but the PaginatorHelper available in views doesn’t always need to be restricted as such.

See the details on PaginatorHelper in the API. As mentioned, the PaginatorHelper also offers sorting features which can be integrated into your table column headers:

<!-- src/Template/Posts/index.ctp -->
        <th><?= $this->Paginator->sort('id', 'ID') ?></th>
        <th><?= $this->Paginator->sort('title', 'Title') ?></th>
       <?php foreach ($recipes as $recipe): ?>
        <td><?= $recipe->id ?> </td>
        <td><?= h($recipe->title) ?> </td>
    <?php endforeach; ?>

The links output from the sort() method of the PaginatorHelper allow users to click on table headers to toggle the sorting of the data by a given field.

It is also possible to sort a column based on associations:

        <th><?= $this->Paginator->sort('title', 'Title') ?></th>
        <th><?= $this->Paginator->sort('', 'Author') ?></th>
       <?php foreach ($recipes as $recipe): ?>
        <td><?= h($recipe->title) ?> </td>
        <td><?= h($recipe->name) ?> </td>
    <?php endforeach; ?>


Sorting by columns in associated models requires setting these in the PaginationComponent::paginate property. Using the example above, the controller handling the pagination would need to set its sortWhitelist key as follows:

$this->paginate = [
    'sortWhitelist' => [

For more information on using the sortWhitelist option, please see Control which Fields Used for Ordering.

The final ingredient to pagination display in views is the addition of page navigation, also supplied by the PaginationHelper:

// Shows the page numbers
<?= $this->Paginator->numbers() ?>

// Shows the next and previous links
<?= $this->Paginator->prev('« Previous') ?>
<?= $this->Paginator->next('Next »') ?>

// Prints X of Y, where X is current page and Y is number of pages
<?= $this->Paginator->counter() ?>

The wording output by the counter() method can also be customized using special markers:

<?= $this->Paginator->counter([
    'format' => 'Page {{page}} of {{pages}}, showing {{current}} records out of
             {{count}} total, starting on record {{start}}, ending on {{end}}'
]) ?>

Paginating Multiple Results

If you are paginating multiple queries you’ll need to set the model option when generating pagination related elements. You can either use the model option on every method call you make to PaginatorHelper, or use options() to set the default model:

// Pass the model option
echo $this->Paginator->sort('title', ['model' => 'Articles']);

// Set the default model.
$this->Paginator->options(['model' => 'Articles']);
echo $this->Paginator->sort('title');

By using the model option, PaginatorHelper will automatically use the scope defined in when the query was paginated.

New in version 3.3.0: Multiple Pagination was added in 3.3.0