cakephp: Paginator 'order' multiple fields not working on second page...
Hello,
I am migrating from Cake 2 to 3 and I am unable to make this part work. When I have multiple order by on the paginator and click on next, only the first parameter is sent in the URL. Is this no longer possible on the nee version?
$this->paginate = [
'order' => [
'Products.color' => 'DESC',
'Products.total' => 'DESC',
'Products.name' => 'ASC'
],
'limit' => 30
];
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 41 (16 by maintainers)
Links to this issue
Commits related to this issue
- Sort albums page by band, then album name (instead of just album name), show 60 at a time (instead of 36). — committed to ltguillaume/sonerezh by ltguillaume 8 years ago
- Use $this->paginate instead of finder and add line to template to fix https://github.com/cakephp/cakephp/issues/7324 as described https://github.com/cakephp/cakephp/issues/7324#issuecomment-218321039.... — committed to mikebirch/cakephp-sponge-blog by mikebirch 7 years ago
Might be late to the game here, but I found a work around for this. In your template file, add this:
$this->Paginator->options( [ 'url'=>[ 'sort'=>null, 'direction'=>null ] ] )This will not generate any sort / direction params on the pagination link, and will retain the original order params in the finder query.
The latest release did not fix this issue (as per @urionlinejudge last comment)
When you set the default order of the paginator to multiple fields there are serious inconsistencies.
The first page is rendered with this order applied (as it is simply passed to the query, which does support multiple order fields)
The “previous”, “next”, and “number” links in this page have the wrong sort options applied to their url. This is apparently done because passing multiple order fields through the url is not supported.
The fact that is not supported is however not the problem, the “solution” for that limitation that was implemented in CakePHP3 (and not in previous version) is the actual problem.
Instead of just not passing the sort options to those links if the sorting hasn’t changed from the default, the code now applies only the first values of the array which, as explained above, gives a wrong result.
If those sort options where not applied to those links in that situation there would be no problem. The url does not need to support passing multiple sort fields.
As i see it there are 2 options:
don’t support multiple sort fields for pagination completely. That means not applying them to the first page! I think this would be a poor choice as it would remove functionality that is needed by (some) people
Don’t apply the sort options to those links in that specific situation.
The code responsible for this problem starts in the PaginatorComponent (paginate function)
The function key() and current() are used to set the sorting, completely ignoring the possibility of multiple sort fields.
I have now extended this component along with the PaginatorHelper to change this to:
And in the helper i change
to
(generateUrl function)
This made it so that if there are multiple sort fields and the sorting hasn’t been changed the sort options are not applied to the links that shouldn’t have them.
This is however a quick-and-dirty workaround, I’m sure that a more complete fix is possible
I would like to make a recommendation to solve this problem:
I extended the PaginatorComponent and changed its line 338 from
$options['order'] = [$options['sort'] => $direction];to$options['order'] = [$options['sort'] => $direction] + $options['order'];This behaviour works for me as I would expect for some reasons:
There might be other cases where this solution is not desired (e.g. if you want to make default sort order before the specified sort order), but for those cases, a simple method in the controller will solve this.
If this solution is accepted, I could make a pull request for this.