Elfalem
Elfalem

Reputation: 357

cakephp 3.2.7 pagination - page option ignored

I'm using CakePHP 3.2.7. In my controller, I'm paginating a table as follows:

class CollectionsController extends AppController
{
public function index()
{
    $page_number = 1;
    $page_size = 10;

    if($this->request->query('page') !== null){
        if(array_key_exists('number', $this->request->query('page'))){
            $page_number = $this->request->query['page']['number'];
        }
        if(array_key_exists('size', $this->request->query('page'))){
            $page_size = $this->request->query['page']['size'];
        }
    }

    $this->paginate = [
        'limit' => $page_size,
        'page' => $page_number,
        //'order' => ['Collections.id' => 'desc']
    ];

    $collections = $this->paginate($this->Collections->find('all'));

    $this->set(compact('collections'));
    $this->set('_serialize', true);
}
}

The paginate options limit and order do work. However, the page and offset (not shown) options seem to be ignored. When printing the contents of $this->request->params['paging'] (when requesting page 2 with size/limit of 2 of a table with 3 rows, query like http://localhost:8765/api/collections?page[number]=2&page[size]=2), I get:

"finder": "all",
"page": 1,
"current": 2,
"count": 3,
"perPage": 2,
"prevPage": false,
"nextPage": true,
"pageCount": 2,
"sort": null,
"direction": false,
"limit": null,
"sortDefault": false,
"directionDefault": false

The perPage option has the value of 2 (which I expect) BUT page has a value of 1 (when it should be 2). Why is the page option being ignored while other pagination options are working?

Upvotes: 0

Views: 1072

Answers (2)

Elfalem
Elfalem

Reputation: 357

I figured out that this had to do with the way I was structuring my url which was conflicting with the default behavior of pagination in CakePHP.

CakePHP automatically processes the page query string. While setting 'page' => $page_number, for paginate options is valid and works, if there is a page query string, it has priority over the paginate option.

In my case, I was following the JSON API example for the pagination url structure. This looks like ?page[number]=3&page[size]=1. Since the query string page was present, it was overriding the paginate option I was setting. However, the value of page in this case was an associative array and not a number as the Paginator component expects. Therefore, the component uses its default value of 1.

This could be resolved by:

  1. Using the default query string as intended (e.g. ?page=2&size=2) (as mentioned by @Jsonras).

  2. Using a different query string that doesn't conflict with page (e.g. ?paging[number]=3&paging[size]=1) and setting the page option as in the question.

  3. Keeping the same structure (?page[number]=3&page[size]=1) and overwriting the value of page query string after parsing the values. In this case, this code in the question,

    $this->paginate = [ 'limit' => $page_size, 'page' => $page_number, ];

would change to:

$this->request->query['page'] = $page_number;
$this->paginate = [
        'limit' => $page_size,
    ];

Upvotes: 1

Jsonras
Jsonras

Reputation: 1160

There is not page option for $this->paginate This is automatically done for you. All you have to do is pass page number.

See this: http://book.cakephp.org/3.0/en/controllers/components/pagination.html

Cake can also generate the pagination links for you. See here: http://book.cakephp.org/3.0/en/views/helpers/paginator.html

If you're trying to build an API, this is the best way to do it using the CURD Plugin: http://www.bravo-kernel.com/2015/04/how-to-build-a-cakephp-3-rest-api-in-minutes/

Upvotes: 0

Related Questions