CakePHP 4 でソートリンクが動かないときの確認事項

はじめに

この記事では CakePHP 4 の Paginator ヘルパーのソート機能が動作しない場合にチェックするポイントをご紹介します。

目次
  1. order() を使っていないか
  2. sortableFields の設定
  3. エイリアス名の有無を統一

1. order() を使っていないか

初期ソートの指定に order() を使うとソートリンクが動作しません。

src/Controller/UsersController.php
// 【注意】動作しません
$query = $this->Users->find()
    ->order(['full_name']);
$users = $this->paginate($query);

下記のように $paginate 変数で指定すれば OK です。

src/Controller/UsersController.php
$this->paginate = [
    'order' => ['full_name'],
];

$query = $this->Users->find();
$users = $this->paginate($query);

2. sortableFields の設定

リレーション先の項目でソートしたい場合には、コントローラの $paginate 変数で sortableFields を指定する必要があります。

src/Controller/UsersController.php
$this->paginate = [
    'sortableFields' => [
        'Users.full_name',
        'Roles.name',
    ]
];

$query = $this->Users->find()
    ->contain(['Roles']);
$users = $this->paginate($query);
templates/Users/index.php
<th><?= $this->Paginator->sort('Users.full_name', '氏名') ?></th>
<th><?= $this->Paginator->sort('Roles.name', '役割') ?></th>

項目名の重複がない場合はテーブルのエイリアス名は未指定でも動作します。

src/Controller/UsersController.php
$this->paginate = [
    'sortableFields' => [
        'full_name',
        'name',
    ]
];
templates/Users/index.php
<th><?= $this->Paginator->sort('full_name', '氏名') ?></th>
<th><?= $this->Paginator->sort('name', '役割') ?></th>

3. エイリアス名の有無を統一

テーブルのエイリアス名の有無は、コントローラ $paginate 変数の order と sortableFields 、テンプレの sort() で統一する必要があります。

例えば下記の場合は、コントローラの sortableFields にはエイリアス名があって、テンプレの sort() の引数には無いので、ソートリンクが機能しません。

src/Controller/UsersController.php
// 【注意】動作しません
// エイリアス名が sotrableFields にはあって、テンプレにはない
$this->paginate = [
    'sortableFields' => [
        'Users.full_name',
        'Roles.name',
    ]
];
templates/Users/index.php
<th><?= $this->Paginator->sort('full_name', '氏名') ?></th>
<th><?= $this->Paginator->sort('name', '役割') ?></th>

また下記の場合は、コントローラの order() で full_name のエイリアス名が無いため、氏名のソートリンクだけが機能しません。

src/Controller/UsersController.php
// 【注意】full_name でソートするときに動作しません
$this->paginate = [
    'order' => [
        // ここだけエイリアス名がない
        'full_name',
    ],
    'sortableFields' => [
        'Users.full_name',
        'Roles.name',
    ]
];
templates/Users/index.php
<th><?= $this->Paginator->sort('Users.full_name', '氏名') ?></th>
<th><?= $this->Paginator->sort('Roles.name', '役割') ?></th>