Ngu ngơ học làm web (x11) - CakePHP2 – Phân trang nâng cao

Tiếp theo của: Ngu ngơ học làm web (x10) - CakePHP2 – Bài tập Link “thân thiện”
-----

Phần x11. CakePHP2 – Phân trang nâng cao


Xem (clip số 17a – chickenrainshop):

Hiển thị category và các book thuộc về category, thực hiện phân trang cho book:

Viết lại action view của controller Categories,

[CategoriesController\view.php]

public function view($slug = null) {
                        $options = [
                                    'conditions' => ['Category.slug' => $slug],
                                    'recursive' => -1
                        ];
                        $category = $this->Category->find('first', $options);
                        if (empty($category)) {
                                    throw new NotFoundException(__('Không tìm thấy thể loại sách này'));
                        }
                        $this->set('category', $category);
                        // phân trang cho các book thuộc thể loại ở trên
                        $this->paginate = [
                                    'fields' => ['id', 'title', 'slug', 'image', 'sale_price'],
                                    'order' => ['created' => 'desc'],
                                    'limit' => 5,
                                    'contain' => [
                                                'Writer' => ['name', 'slug'],
                                                'Category' => ['slug']
                                                ],
                                    'conditions' => [
                                                'published' => 1,
                                                'Category.slug' => $slug
                                                ],
                                    'paramType' => 'querystring'
                        ];
                        $books = $this->paginate('Book');
                        $this->set('books', $books);
            }

Ý nghĩa của hàm $this->paginate() ở đoạn mã trên là:

- lấy thông tin của sách, gồm:  ('id', 'title', 'slug', 'image', 'sale_price')

- lấy thêm thông tin về tác giả (writer) của sách: ('contain' => ['Writer' => ['name', 'slug']])

- chỉ lấy các cuốn sách có cùng thể loại: ('Category.slug' => $slug)

- vì vậy cần phải lấy thêm thông tin về thể loại của sách: ('contain' => ['Category' => ['slug']])

[View\Categories\view.php]

<div class="categories view">
<h2><?php echo __('Category'); ?></h2>
            <dl>
                        <dt><?php echo __('Name'); ?></dt>
                        <dd>
                                    <?php echo h($category['Category']['name']); ?>
                                    &nbsp;
                        </dd>
                        <dt><?php echo __('Description'); ?></dt>
                        <dd>
                                    <?php echo h($category['Category']['description']); ?>
                                    &nbsp;
                        </dd>
            </dl>
</div>
<div class="related">
            <h3><?php echo __('Related Books'); ?></h3>
            <?php if (!empty($books)): ?>
                        <?php echo $this->element('book', ['books' => $books]); ?>
                        <?php echo $this->element('pagination', ['object' => 'quyển sách']); ?>
            <?php endif; ?>
</div>

Học thêm cách viết lệnh if:

<?php if( ): ?>
            // đoạn lệnh trong if
<?php endif; ?>

Ở đoạn mã trên thấy có hàm h(), hàm này để làm gì?

Đọc về hàm h() tại đây: https://api.cakephp.org/2.7/function-h.html

Hàm h() là một hàm của CakePHP, nó thực chất là hàm htmlspecialchars của PHP.

Hàm htmlspecialchars để làm gì?

Đọc thêm về hàm htmlspecialchar tại đây: http://php.net/manual/en/function.htmlspecialchars.php

Hàm htmlspecialchars để chuyển các kí tự đặc biệt sang dạng htmlentities, ví dụ:

Kí tự
Được thay bằng (dạng htmlentities)
& (ampersand)
&amp;
“ (double quote)
&quot;
‘ (single quote)
&#039;
< (less than)
&lt;
> (greater than)
&gt;

Chạy thử ví dụ sau, để hiểu thêm về hàm h:

<?php
            $test = "<b>Có in đậm không</b>";
            echo h($test); // trình duyệt sẽ không thực thi thẻ html
            echo $test; // trình duyệt có thực thi thẻ html
?>
Cấu hình route cho link phân trang:

Khi bấm vào các link trong phần phân trang, đường dẫn sẽ có dạng sau:

-> cần phải cấu hình lại trong routes.php

Chuyển dòng này:

Router::connect('/danh-muc/:name', ['controller' => 'categories', 'action' => 'view'], ['pass' => 
['name']]);

Thành,

Router::connect('/danh-muc/*', ['controller' => 'categories', 'action' => 'view']);

Trong đó, dấu ‘*’ đại diện cho chuỗi bất kì.

Xem (clip số 17b – chickenrainshop):

Phân trang dữ liệu với quan hệ nhiều - nhiều.

Ví dụ, hiển thị writer và các book thuộc về writer, thực hiện phân trang cho book:

Lệnh joins (phút 3:10).

Lệnh joins để kết nối bảng: books với books_writers, và books với writers.  

$this->paginate = [
                                    'fields' => ['id', 'title', 'slug', 'image', 'sale_price'],
                                    'order' => ['created' => 'desc'],
                                    'limit' => 2,
                                    'contain' => [
                                                'Writer' => ['name', 'slug']
                                                ],
                                    'joins' => [
                                                [
                                                            'table' => 'books_writers',
                                                            'alias' => 'BookWriter',
                                                            'conditions' => 'BookWriter.book_id = Book.id'
                                                ],
                                                [
                                                            'table' => 'writers',
                                                            'alias' => 'Writer',
                                                            'conditions' => 'BookWriter.writer_id = Writer.id'
                                                ]
                                    ],
                                    'conditions' => [
                                                'published' => 1,
                                                'Writer.slug' => $slug
                                                ],
                                    'paramType' => 'querystring'
                        ];

[action view trong WritersController.php]

            public function view($slug = null) {
                        $options = [
                                    'conditions' => [
                                                'Writer.slug' => $slug
                                                ],
                                    'recursive' => -1
                        ];
                        $writer = $this->Writer->find('first', $options);
                        if(empty($writer)) {
                                    throw new NotFoundException(__('Không tìm thấy tác giả này!'));
                        }
                        $this->set('writer', $writer);
                        // phân trang cho các book thuộc tác giả ở trên
                        $this->paginate = [
                                    'fields' => ['id', 'title', 'slug', 'image', 'sale_price'],
                                    'order' => ['created' => 'desc'],
                                    'limit' => 2,
                                    'contain' => [
                                                'Writer' => ['name', 'slug']
                                                ],
                                    'joins' => [
                                                [
                                                            'table' => 'books_writers',
                                                            'alias' => 'BookWriter',
                                                            'conditions' => 'BookWriter.book_id = Book.id'
                                                ],
                                                [
                                                            'table' => 'writers',
                                                            'alias' => 'Writer',
                                                            'conditions' => 'BookWriter.writer_id = Writer.id'
                                                ]
                                    ],
                                    'conditions' => [
                                                'published' => 1,
                                                'Writer.slug' => $slug
                                                ],
                                    'paramType' => 'querystring'
                        ];
                        $books = $this->paginate('Book');
                        $this->set('books', $books);
            }

[View Writers\ view.ctp]

<div class="writers view">
<h2><?php echo __('Writer'); ?></h2>
            <dl>
                        <dt><?php echo __('Name'); ?></dt>
                        <dd>
                                    <?php echo h($writer['Writer']['name']); ?>
                                    &nbsp;
                        </dd>
                        <dt><?php echo __('Biography'); ?></dt>
                        <dd>
                                    <?php echo h($writer['Writer']['biography']); ?>
                                    &nbsp;
                        </dd>
            </dl>
</div>
<div class="related">
            <h3><?php echo __('Related Books'); ?></h3>
            <?php if (!empty($books)): ?>
                        <?php echo $this->element('book', ['books' => $books]); ?>
                        <?php echo $this->element('pagination', ['object' => 'quyển sách']); ?>
            <?php endif; ?>
</div>

[routes.php]

Sửa dòng mã:

Router::connect('/tac-gia/:name', ['controller' => 'writers', 'action' => 'view'], ['pass' => ['name']]);
Thành:


Router::connect('/tac-gia/*', ['controller' => 'writers', 'action' => 'view']);
-----------
Cập nhật 28/4/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x10) - CakePHP2 - Bài tập Link "thân thiện"

Tiếp theo của: Ngu ngơ học làm web (x9) - CakePHP2 – Tạo link "thân thiện"
-----

Phần x10. CakePHP2 – Bài tập Link “thân thiện”


Xem (clip số 16BT – chickenrainshop):

1. Tạo link “thân thiện” cho chức năng xem phân loại sách

Hiện tại đường dẫn của chức năng phân loại sách có dạng:

Nghĩa là action view đang truy vấn dựa theo id, giờ sẽ viết lại hàm view, để nó truy vấn theo trường slug của bảng categories.

[CategoriesController.php, action view]

public function view($slug = null) {
                        $options = [
                                    'conditions' => ['Category.slug' => $slug]
                        ];
                        $category = $this->Category->find('first', $options);
                        if (empty($category0)) {
                                    throw new NotFoundException(__('Không tìm thấy thể loại sách này'));
                        }
                        $this->set('category', $category);
            }

Yêu cầu cần làm tiếp theo là chuyển đường dẫn truy vấn dạng:


Về dạng:

http://local.chickenrainshop/danh-muc /slug

Mở tập tin routes.php, và thêm vào dòng mã sau:

Router::connect('/danh-muc/:name', ['controller' => 'categories', 'action' => 'view'], ['pass' => ['name']]);

2. Tạo link “thân thiện” cho chức năng xem thông tin tác giả

[WritersController.php, action view] viết lại như sau:

public function view($slug = null) {
                        $options = [
                                    'conditions' => ['Writer.slug' => $slug]
                        ];
                        $writer = $this->Writer->find('first', $options);
                        if(empty($writer)) {
                                    throw new NotFoundException(__('Không tìm thấy tác giả này!'));
                        }
                        $this->set('writer', $writer);
            }

[routes.php] thêm dòng mã sau:


Router::connect('/tac-gia/:name', ['controller' => 'writers', 'action' => 'view'], ['pass' => ['name']]);
-----------
Cập nhật 28/4/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x9) - CakePHP2 - Tạo link "thân thiện"

Tiếp theo của: Ngu ngơ học làm web (x8) - CakePHP2 – Element
-----

Phần x9. CakePHP2 – Tạo link “thân thiện”


Xem (clip số 15 – chickenrainshop):

Một link (đường dẫn tới một tài nguyên trên mạng) bình thường sẽ có dạng:

http://tên_miền/controller/action/id

Ví dụ,


Một link được gọi là “thân thiện” sẽ có dạng:

http://tên_miền/ten-cua-doi-tuong

Ví dụ,

Để chuyển từ link bình thường sang dạng link “thân thiện” cần thực hiện hai việc:

- Trong link, thay thế vai trò của id bằng ten-cua-doi-tuong (trường slug trong bảng dữ liệu)

- Cấu hình route để chuyển từ  http://tên_miền/controller/action/id sang dạng http://tên_miền/ten-cua-doi-tuong

Làm theo ví dụ trong clip số 15,

Viết lại hàm view trong controller Books, thay vì tìm cuốn sách theo id, sẽ chuyển thành tìm cuốn sách theo slug.

[BooksController.php]
            public function view($slug = null) {
                        $options = [
                                    'conditions' => ['Book.slug' => $slug]
                                    ];
                        $book = $this->Book->find('first', $options);
                        if (empty($book)) {
                                    throw new NotFoundException(__('Không tìm thấy quyển sách này'));
                        }
                        $this->set('book', $book);
            }

Cấu hình route để chuyển từ  http://tên_miền/controller/action/id sang dạng http://tên_miền/ten-cua-doi-tuong:

Vào Config, mở tập tin routes.php, thêm vào dòng lệnh sau:

Router::connect('/:book_title', ['controller' => 'books', 'action' => 'view'], ['pass' => ['book_title']]);

Đọc thêm về routing tại đây: https://book.cakephp.org/2.0/en/development/routing.html để hiểu dòng mã trên.

Có thể hiểu nó như sau:

1. Khi người dùng nhập vào thanh địa chỉ của trình duyệt một đường dẫn có dạng ‘/:book_title’, ở đây:

- Dấu ‘/’ tương đương với thư mục gốc của web (ví dụ: local.chickenrain)

-  ‘:book_title’ là một chuỗi bất kì, đóng vai trò là tham số, và sẽ được sử dụng để truyền vào cho action, ví dụ ‘kham-pha-ngon-ngu-tu-duy’

2. ['controller' => 'books', 'action' => 'view']  nghĩa là website sẽ gọi action (hàm) view trong controller Books.

3. ['pass' => ['book_title'] có nghĩa là chuyển cái chuỗi book_title thành tham số cho action view.

Trong tập tin routes.php, có thể thay dòng mã:

Router::connect('/:book_title', ['controller' => 'books', 'action' => 'view'], ['pass' => ['book_title']]);

Bằng dòng mã sau:

Router::connect('/:chuoi_bat_ki', ['controller' => 'books', 'action' => 'view'], ['pass' => 
['chuoi_bat_ki']]);

Thì website vẫn chạy bình thường.

Phần tiếp theo sẽ gắn giá trị của trường slug vào một mục nào đó trên giao diện, để khi người dùng bấm vào, thì website sẽ thực hiện truy vấn dựa trên giá trị slug.

Ví dụ, thực hiện trên view Books\index (để ý dòng tô đậm), :

<div class="books index">
            <h2><?php echo __('Sách mới'); ?></h2>
            <h4><?php echo $this->Html->link('Xem thêm','/sach-moi') ?></h4>
            <?php foreach($books as $book): ?>
                        <?php echo $this->Html->link($book['Book']['title'], '/'.$book['Book']['slug']); ?> <br>
                        <?php echo $this->Html->image($book['Book']['image'], ['width' => '60px', 'height' => '80px']); ?> <br>
                        Giá bán:<?php echo $this->Number->currency($book['Book']['sale_price'],' VND',['places' => 0,'wholePosition' => 'after']); ?> <br>
                        <?php foreach($book['Writer'] as $writer): ?>
                                    <?php echo $writer['name'].' '; ?>
                        <?php endforeach; ?>
                        <br>
                        <br>
                        <hr>
                        <br>
            <?php endforeach; ?>
</div>

Do mã trong view Books\index và Books\latest_books tương tự nhau, nên sẽ gom lại thành một element, đặt tên cho element này là book.

[View\Elements\book.ctp]
<?php foreach($books as $book): ?>
            <?php echo $this->Html->link($book['Book']['title'], '/'.$book['Book']['slug']); ?> <br>
            <?php echo $this->Html->image($book['Book']['image'], ['width' => '60px', 'height' => '80px']); ?> <br>
            Giá bán:<?php echo $this->Number->currency($book['Book']['sale_price'],' VND',['places' => 0,'wholePosition' => 'after']); ?> <br>
            <?php foreach($book['Writer'] as $writer): ?>
                        <?php echo $writer['name'].' '; ?>
            <?php endforeach; ?>
            <br>
            <br>
            <hr>
            <br>
<?php endforeach; ?>

Gọi element trong các view khác:

[View\Books\index.ctp]
<div class="books index">
            <h2><?php echo __('Sách mới'); ?></h2>
            <h4><?php echo $this->Html->link('Xem thêm','/sach-moi') ?></h4>
            <?php echo $this->element('book', ['books' => $books]); ?>
</div>

[View\Books\latest_books.ctp]
<div class="books index">
            <h2><?php echo __('Sách mới'); ?></h2>
            <p>
                        <?php echo $this->paginator->sort('title','Sắp xếp theo tên sách'); ?>
            </p>
            <?php echo $this->element('book', ['books' => $books]); ?>
            <?php echo $this->element('pagination', ['object' => 'quyển sách']); ?>

</div>
-----------
Cập nhật 26/4/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x8) - CakePHP2 - Element

Tiếp theo của: Ngu ngơ học làm web (x7) - CakePHP2 – Bài tập Phân trang
-----

Phần x8. CakePHP2 – Element


Xem (clip số 14 – chickenrainshop):

Element là các đoạn mã của view được sử dụng lại ở nhiều nơi, element còn được gọi là mini-view. 

Đọc thêm về element tại đây: https://book.cakephp.org/2.0/en/views.html#elements

Ví dụ, đoạn mã phân trang ở hai view: index và latest_book có thể viết lại dưới dạng một element, sau đó tại mỗi view sẽ gọi element.

Thư mục View\Elements là nơi chứa các element.

Ví dụ tạo một element có tên là pagination.ctp trong View\Elements,

 [pagination.ctp]
            <p>
                        <?php echo $this->Paginator->counter("Trang {:page}/{:pages}, hiển thị {:current} ".$object." trong tổng số {:count} ". $object . "."); ?> <br>
                        <?php echo $this->Paginator->prev('Quay lại'); ?>
                        <?php echo $this->Paginator->numbers([
                                    'separator' => ' - ',
                                    'before' => '| ',
                                    'after' => ' |'
                                    ]); ?>
                        <?php echo $this->Paginator->next('Kế tiếp'); ?>
            </p>

Trong View\Writers\index.ctp sẽ gọi element pagination, để ý là khi gọi element pagination thì phải gửi biến $object từ index.ctp qua cho pagination.ctp, dòng này:

<?php echo $this->element('pagination', ['object' => 'tác giả']); ?>

[index.ctp]
<div class="writers index">
            <h2><?php echo __('Các tác giả'); ?></h2>
            <h4><?php echo $this->paginator->sort('name', 'Xếp theo thứ tự ngược lại'); ?></h4>
            <?php foreach($writers as $writer): ?>
            <?php echo $writer['Writer']['name'] ?> <br>
            <?php endforeach ?>
            <br>
            <hr>
            <br>
            <?php echo $this->element('pagination', ['object' => 'tác giả']); ?>
</div>

Còn đoạn mã dưới đây là gọi element pagination trong View\Books\latest_books.ctp

[latest_books.ctp]
<div class="books index">
            <h2><?php echo __('Sách mới'); ?></h2>
            <p>
                        <?php echo $this->paginator->sort('title','Sắp xếp theo tên sách'); ?>
            </p>
            <?php foreach($books as $book): ?>
                        <?php echo $book['Book']['title']; ?> <br>
                        <?php echo $this->Html->image($book['Book']['image'], ['width' => '60px', 'height' => '80px']); ?> <br>
                        Giá bán:<?php echo $this->Number->currency($book['Book']['sale_price'],' VND',['places' => 0,'wholePosition' => 'after']); ?> <br>
                        <?php foreach($book['Writer'] as $writer): ?>
                                    <?php echo $writer['name'].' '; ?>
                        <?php endforeach; ?>
                        <br>
                        <br>
                        <hr>
                        <br>
            <?php endforeach; ?>
            <?php echo $this->element('pagination', ['object' => 'quyển sách']); ?>

</div>
-----------
Cập nhật 26/4/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x7) - CakePHP2 - Bài tập Phân trang

Phần x7. CakePHP2 – Bài tập Phân trang


Xem (clip số 13 – chickenrainshop):

Bài tập về phân trang, thực hiện phân trang cho trang hiển thị các tác giả.


Vào Config/routes.php, thêm vào dòng mã sau:

Router::connect('/tac-gia', ['controller' => 'writers', 'action' => 'index']);

2. Hiển thị nội dung và phân trang

Hàm index trong controller Writers

public function index() {
                        $this->paginate=[
                                    'fields' => ['name', 'slug'],
                                    'limit' => 5,
                                    'order' => ['name' => 'ASC'],
                                    'paramType' => 'querystring'
                        ];
                        $writers = $this->paginate();
                        $this->set('writers', $writers);
            }

Tập tin index.ctp trong view Writers

<div class="writers index">
            <h2><?php echo __('Các tác giả'); ?></h2>
            <h4><?php echo $this->paginator->sort('name', 'Xếp theo thứ tự ngược lại'); ?></h4>
            <?php foreach($writers as $writer): ?>
            <?php echo $writer['Writer']['name'] ?> <br>
            <?php endforeach ?>
            <br>
            <hr>
            <br>
            <p>
                        <?php echo $this->paginator->counter('Trang {:page}/{:pages}, hiển thị {:current} tác giả trong tổng số {:count} tác giả.'); ?> <br>
                        <?php echo $this->paginator->prev('Quay lại'); ?>
                        <?php echo $this->paginator->numbers([
                                    'separator' => ' - ',
                                    'before' => '| ',
                                    'after' => ' |'
                                    ]); ?>
                        <?php echo $this->paginator->next('Kế tiếp'); ?>
            </p>

</div>
-----------
Cập nhật 25/4/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web

Ngu ngơ học làm web (x6) - CakePHP2 - Phân trang

Tiếp theo của: Ngu ngơ học làm web (x5) - CakePHP2 – Tạo home page
------

Phần x6. CakePHP2 – Phân trang


Xem (clip số 12 – chickenrainshop):

Tạo link bằng html helper (phút 1:00).

<h4><?php echo $this->Html->link('Xem thêm','/sach-moi') ?></h4>

Trong đó ‘Xem thêm’ là tên hiển thị, ‘/sach-moi’ là đường dẫn của trang được link.

Tuy nhiên ‘/sach-moi’ không tuân theo cú pháp: ‘/controller/action’, nên cần phải cấu hình một dòng lệnh trong Config/routes.php để ánh xạ từ ‘/sach-moi’ sang cú pháp ‘/controller/action’. Ví dụ,

Router::connect('/sach-moi', ['controller' => 'books', 'action' => 'latest_books']);

Do chưa có action latest_books, nên phải vào controller Books để tạo action này.

Sử dụng phương thức $this->paginate() trong controller để lấy dữ liệu cho phân trang (phút 5:17).

Số mẩu tin mặc định của paginate() trả về là 20.

Có thể tùy biến, thiết lập thêm các tham số cho biến $paginate ở đầu controller, Ví dụ,

public $paginate = [
                                    'order' => ['created' => 'desc'],
                                    'limit' => 5
                        ];

Hoặc có thể tùy biến, thiết lập thêm các tham số cho biến $paginate ngay trong action, ví dụ,

public function latest_books() {
                        $this->paginate = [
                                    'fields' => ['id', 'title', 'slug', 'image', 'sale_price'],
                                    'order' => ['created' => 'desc'],
                                    'limit' => 5,
                                    'contain' => ['Writer' => ['name', 'slug']
                                                ],
                                    'conditions' => ['published' => 1]
                        ];
                        $books = $this->paginate();
                        $this->set('books', $books);    
            }

Tạo thêm view latest_books.ctp.

<div class="books index">
            <h2><?php echo __('Sách mới'); ?></h2>
            <?php foreach($books as $book): ?>
                        <?php echo $book['Book']['title']; ?> <br>
                        <?php echo $this->Html->image($book['Book']['image'], ['width' => '60px', 'height' => '80px']); ?> <br>
                        Giá bán:<?php echo $this->Number->currency($book['Book']['sale_price'],' VND',['places' => 0,'wholePosition' => 'after']); ?> <br>
                        <?php foreach($book['Writer'] as $writer): ?>
                                    <?php echo $writer['name'].' '; ?>
                        <?php endforeach; ?>
                        <br>
                        <br>
                        <hr>
                        <br>
            <?php endforeach; ?>
</div>

Xem (clip số 12b – chickenrainshop):


Sử dụng helper paginator để phân trang (phút 0:00).

Để tạo link nhằm sắp xếp các item trên một trang, sử dụng hàm sort() của helper paginator, ví dụ, trong view latest_books, dưới đoạn mã:

<div class="books index">
            <h2><?php echo __('Sách mới'); ?></h2>

thêm đoạn mã sau:

<p>
<?php echo $this->paginator->sort('title','Sắp xếp theo tên sách'); ?>
</p>

Cú pháp của hàm sort:

sort(‘trường được sử dụng để sắp xếp’, ‘dòng thông báo hiển thị ở giao diện’

Để xuất thông tin về trang hiện tại sử dụng hàm counter() của helper paginator, ví dụ, trong view latest_books, trước thẻ </div> ở cuối tập tin, thêm đoạn mã sau:

<p>
            <?php echo $this->paginator->counter("Trang {:page}/{:pages}, hiển thị {:current} quyển sách trong tổng số {:count} quyển."); ?>
</p>

Trong đó, các biến có sẵn của paginator có ý nghĩa như sau:

- {:page}: trang hiện tại

- {:pages}: tổng số trang

- {:current}: số item trên trang hiện tại

- {:count}: tổng số item

Để hiển thị danh sách các trang, nút bấm để đi đến trang trước, trang sau; sử dụng các hàm tương ứng: numbers(), prev(), next() của helper paginator. Ví dụ,

<p>
            <?php echo $this->paginator->counter("Trang {:page}/{:pages}, hiển thị {:current} quyển sách trong tổng số {:count} quyển."); ?> <br>
            <?php echo $this->paginator->prev('<< Trang trước'); ?>
            <?php echo $this->paginator->numbers(); ?>
            <?php echo $this->paginator->next('Trang sau >>'); ?>
</p>

Để chuyển URL “dạng phân trang” sang “dạng GET”:

Ví dụ URL “dạng phân trang”,


chuyển sang “dạng GET”,


cần thêm tùy chọn ‘paramType’ => ‘querystring’ vào biến paginate, cụ thể,

$this->paginate = [
                                    'fields' => ['id', 'title', 'slug', 'image', 'sale_price'],
                                    'order' => ['created' => 'desc'],
                                    'limit' => 5,
                                    'contain' => ['Writer' => ['name', 'slug']
                                                ],
                                    'conditions' => ['published' => 1],
                                    'paramType' => 'querystring'

                        ];
-----------
Cập nhật 24/4/2017
-----------
Xem thêm:
Tổng hợp các bài viết về Ngu ngơ học làm web
Ngu ngơ học làm web (x7) - CakePHP2 - Bài tập Phân trang