Step-by-Step Tutorial on Creating Pagination in CakePHP 4

Pagination is an essential part of web development that allows users to navigate through a large list of data easily. It divides the data into small chunks and displays them in a structured and manageable way.

In CakePHP 4 you don’t need to write lots of code to create a pagination list. For this paginate() method is available that executes from the controller.

In this tutorial, I show how you can create a pagination in CakePHP 4 with MySQL database data.

Step-by-Step Tutorial on Creating Pagination in CakePHP 4


Contents

  1. Create Table
  2. Database Configuration
  3. Create Model
  4. Create Controller
  5. Create Template
  6. Output
  7. Conclusion

1. Create Table

In the example, I am using users Tables. It has the following structure and data –

CREATE TABLE `users` (
    `id` int(11) NOT NULL,
    `username` varchar(50) NOT NULL,
    `name` varchar(60) NOT NULL,
    `gender` varchar(10) NOT NULL,
    `email` varchar(60) NOT NULL,
    `city` varchar(80) NOT NULL
);

ALTER TABLE `users`
    ADD PRIMARY KEY (`id`);

ALTER TABLE `users`
    MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

INSERT INTO `users` (`id`, `username`, `name`, `gender`, `email`, `city`) VALUES
(1, 'yssyogesh', 'Yogesh singh', 'male', 'yogesh@makitweb.com', 'Bhopal'),
(2, 'bsonarika', 'Sonarika Bhadoria', 'female', 'bsonarika@makitweb.com', 'Indore'),
(3, 'sunil', 'Sunil singh', 'male', 'sunil@makitweb.com', 'Pune'),
(4, 'vishal', 'Vishal Sahu', 'male', 'vishal@makitweb.com', 'Bhopal'),
(5, 'jiten', 'jitendra singh', 'male', 'jitendra@makitweb.com', 'Delhi'),
(6, 'shreya', 'Shreya joshi', 'female', 'shreya@makitweb.com', 'Indore'),
(7, 'abhilash', 'Abhilash namdev', 'male', 'abhilash@makitweb.com', 'Pune'),
(8, 'ekta', 'Ekta patidar', 'female', 'ekta@makitweb.com', 'Bhopal'),
(9, 'deepak', 'Deepak singh', 'male', 'deepak@makitweb.com', 'Delhi'),
(10, 'rohit', 'Rohit Kumar', 'male', 'rohit@makitweb.com', 'Bhopal'),
(11, 'bhavna', 'Bhavna Mahajan', 'female', 'bhavna@makitweb.com', 'Indore'),
(12, 'ajay', 'Ajay singh', 'male', 'ajay@makitweb.com', 'Delhi'),
(13, 'mohit', 'Mohit', 'male', 'mohit@makitweb.com', 'Pune'),
(14, 'akhilesh', 'Akhilesh Sahu', 'male', 'akhilesh@makitweb.com', 'Indore'),
(15, 'ganesh', 'Ganesh', 'male', 'ganesh@makitweb.com', 'Pune'),
(16, 'vijay', 'Vijay', 'male', 'vijay@makitweb.com', 'Delhi');

2. Database Configuration

  • Open config/app_local.php file.
  • Specify your database configuration details in the Datasources default.
'Datasources' => [
     'default' => [
          'host' => '127.0.0.1',
          /*
          * CakePHP will use the default DB port based on the driver selected
          * MySQL on MAMP uses port 8889, MAMP users will want to uncomment
          * the following line and set the port accordingly
          */
          //'port' => 'non_standard_port_number',

          'username' => 'root',
          'password' => 'root',

          'database' => 'cakephp4',
          /*
          * If not using the default 'public' schema with the PostgreSQL driver
          * set it here.
          */
          //'schema' => 'myapp',

          /*
          * You can use a DSN string to set the entire configuration
          */
          'url' => env('DATABASE_URL', null),
     ],

     /*
     * The test connection is used during the test suite.
     */
     'test' => [
          'host' => 'localhost',
          //'port' => 'non_standard_port_number',
          'username' => 'my_app',
          'password' => 'secret',
          'database' => 'test_myapp',
          //'schema' => 'myapp',
          'url' => env('DATABASE_TEST_URL', 'sqlite://127.0.0.1/tests.sqlite'),
     ],
],

3. Create Model

  • Create Users Model.
bin/cake bake model Users
  • This will create 2 files –
src/Model/Entity/User.php
src/Model/Table/UsersTable.php

src/Model/Entity/User.php

In this Entity class specify field names that you want to allow insertion and updation. You can either remove the field name or set it to false if you don’t want to allow.

Completed Code

<?php
declare(strict_types=1);

namespace App\Model\Entity;

use Cake\ORM\Entity;

class Users extends Entity
{

      protected $_accessible = [
           'username' => true,
           'name' => true,
           'age' => true,
           'gender' => true,
           'email' => true,
           'city' => true,
      ];
}

src/Model/Table/UsersTable.php

This Table class tells ORM which table needs to use and defines validation rules for the fields.

Completed Code

<?php
declare(strict_types=1);

namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

class UsersTable extends Table
{

      public function initialize(array $config): void
      {
            parent::initialize($config);

            $this->setTable('users');
            $this->setDisplayField('name');
            $this->setPrimaryKey('id');
      }

      public function validationDefault(Validator $validator): Validator
      {
            $validator
            ->scalar('username')
            ->maxLength('username', 50)
            ->requirePresence('username', 'create')
            ->notEmptyString('username');

            $validator
            ->scalar('name')
            ->maxLength('name', 60)
            ->requirePresence('name', 'create')
            ->notEmptyString('name');

            $validator
            ->integer('age')
            ->requirePresence('age', 'create')
            ->notEmptyString('age');
 
            $validator
            ->scalar('gender')
            ->maxLength('gender', 10)
            ->requirePresence('gender', 'create')
            ->notEmptyString('gender');

            $validator
            ->email('email')
            ->requirePresence('email', 'create')
            ->notEmptyString('email');

            $validator
            ->scalar('city')
            ->maxLength('city', 80)
            ->requirePresence('city', 'create')
            ->notEmptyString('city');

            return $validator;
      }

      public function buildRules(RulesChecker $rules): RulesChecker
      {
            $rules->add($rules->isUnique(['username']), ['errorField' => 'username']);

            return $rules;
      }
}

4. Create Controller

  • Create a UsersController.php file in src/Controller/ folder.
  • Create UsersController Class that extends AppController.

Create 1 method –

  • index() – Create an object of Users Table using – $this->getTableLocator()->get('Users').

I am paginating all users table records. If you want to paginate specific records then you can set where clause using $query$query->where();.

In the $settings Array set limit and default order by column name. I set a limit of 5 and order by name field in asc order.

Call $this->paginate() to create pagination. Here, pass $query and $settings.

Using $this->set() pass $users to the template.

Completed Code

<?php
declare(strict_types=1);

namespace App\Controller;

class UsersController extends AppController
{

     public function index(){

          $UsersTable = $this->getTableLocator()->get('Users');

          // Paginate the ORM table.
          $query = $UsersTable->find('all');

          // Settings
          $settings = [
               'limit'=> '5',
               'order' => ['Users.name' => 'asc']
          ];

          $users = $this->paginate($query,$settings );

          $this->set(compact('users'));

     }

}

5. Create Template

Create Users folder in templates/ location. In the Users folder create index.php file – templates/Users/index.php.

Create Pagination layout –

Create <table >.

  • Sorting –

Add header columns and with the use of Paginator helper allow sorting on the header column name click –

<?= $this->Paginator->sort('id', 'ID') ?>

Here, the first parameter is the sorting column name and 2nd parameter is the Column title.

For example purpose, I have not set sorting on the Email column.

  • List paginated data –

Loop on the $users if it is not empty. Read values and add new <tr> <td>.

  • Pagination Navigation links –

Again use Paginator helper for adding navigation links. I am adding the Previous, next, and number lists.

Completed Code

<div class="row">
     <div class="col-6">

          <!-- User paginated list -->
          <table >
              <thead>
                  <tr>
                      <th><?= $this->Paginator->sort('id', 'ID') ?></th>
                      <th><?= $this->Paginator->sort('username', 'Username') ?></th>
                      <th><?= $this->Paginator->sort('id', 'Name') ?></th>
                      <th><?= $this->Paginator->sort('id', 'Gender') ?></th>
                      <th><?= $this->Paginator->sort('id', 'Age') ?></th>
                      <th>Email</th>
                      <th><?= $this->Paginator->sort('id', 'City') ?></th>
                  </tr>
              </thead>
              <tbody>
                   <?php if(count($users) > 0):?>
                        <?php foreach ($users as $user): ?>
                            <tr>
                                <td><?= $user['id'] ?></td>
                                <td><?= $user['username'] ?></td>
                                <td><?= $user['name'] ?></td>
                                <td><?= $user['gender'] ?></td>
                                <td><?= $user['age'] ?></td>
                                <td><?= $user['email'] ?></td>
                                <td><?= $user['city'] ?></td>
                            </tr>
                        <?php endforeach; ?>
                   <?php else: ?>
                        <tr>
                            <td colspan="7">No record found.</td>
                        </tr>
                   <?php endif; ?> 
              </tbody>
          </table>

          <!-- Pagination links -->
          <ul class="pagination">
              <?= $this->Paginator->prev("<<") ?>
              <?= $this->Paginator->numbers() ?>
              <?= $this->Paginator->next(">>") ?>
          </ul>
     </div>

</div>

6. Output

View Output


7. Conclusion

Call the paginate() method in the controller to create the pagination of your data. Display it in the template by looping on the generated data and using the Paginator helper.

View this official document for pagination creation if you want to learn more about it.

You can also check out more CakePHP 4 tutorials on the site.

If you found this tutorial helpful then don't forget to share.

Leave a Comment