cakephp

Paginating with sort and direction


Cakephp Version: 5.0.10

Hi,

Tickets Controller - The Process

The page is initially loaded and I initialise the limit from the database and store in a setter with:

 $this->setLimit($user->results_per_page->respp_ticket);

I also hard code the sort and direction and store in setters with:

$this->setSort('Tickets.date_created');
$this->setDirection('desc');

I paginate the query with.

$tickets = $this->paginate($query);
$this->set(compact('tickets'));

I apply the limit, sort and direction to the query like this:

$this->paginate = [
    'limit' => $this->getLimit(),
    'order' => [
        $this->getSort() => $this->getDirection(),
    ],
];

$tickets = $this->paginate($query);
$this->set(compact('tickets')); 

The limit, sort and direction have been applied to the query correctly. And you can sort on any column correctly.

The page numbers however do not contain the sort and direction in the url.

QUESTION

Is there anyway to pass the sort and direction in the url via the paginations page numbers so I can initialise them in the tickets controller after I click the page numbers?

What else I've tried

If I initialise the pagination like the following the sort and direction are in the url when the page numbers are clicked.

$this->paginate = [
    'limit' => $this->getLimit(),
    'sort' => $this->getSort(),
    'direction' => $this->getDirection(),
];

But this error is displayed in the view:

Warning (512) : Passing query options as paginator settings is no longer supported. Use a custom finder through the finder config or pass a SelectQuery instance to paginate(). Extra keys found are: sort, direction.

QUESTION

How do I configure a finder to initialise the sort and direction?

Thanks Zenzs


Solution

  • The answer basically is you can't.

    If you use the pagination property to apply the initial loads sort, direction and limit they will not be in the url. The framework will automatically apply them.

    But if there in the url the framework will prioritise them over the pagination property parameters.

    Therefore the answer was to not hard code them in the pagination property but to hard code them in a redirect on initial load like the below example.

    Tickets Controller

    protected array $paginate = [
        'sortableFields' => [
            'id',
            'user_id',
            'title',
            'slug',
            'published',
            'created',
            'modified'
        ]
    ];
    
    public function index()
    {
        if (is_null($this->request->getQuery('sort'))
            && is_null($this->request->getQuery('direction'))
            && is_null($this->request->getQuery('limit'))) {
    
            /**
             * INITIAL LOAD
             */
            $redirect = $this->request->getQuery('redirect', [
                'action' => 'index',
                '?' => [
                    'sort' => 'title',
                    'direction' => 'asc',
                    'limit' => 2 // This value of 2 comes from the database in my app.
                ]
            ]);
    
            return $this->redirect($redirect);
            exit(0);
        }
    
        /**
         * OTHER LOADS
         */
        $page = $this->request->getQuery('page');
        $sort = $this->request->getQuery('sort');
        $direction = $this->request->getQuery('direction');
        $limit = $this->request->getQuery('limit');
    
        $query = $this->Articles->find('myArticles',
            user_id: 1
        );
    
        $articles = $this->paginate($query);
        $this->set(compact('articles'));
    
        $this->set('page', $page);
        $this->set('sort', $sort);
        $this->set('direction', $direction);
        $this->set('limit', $limit);
    }
    

    This ensures there in the url and you can access them in the view on initial load.

    Why might you want them in the view. To store in hidden fields and POST them to another function, append them to a redirect back to index in that function which means the framework will apply them to the result set after a PRG (Post, Redirect, Get).

    For more information and examples on v4 and v5 baked code please see my post here.