CakePHP 分页排序包含数据
CakePHP Paginate Sort on Contain Data
这是一个用于跟踪用户爱好的简单应用程序。一个用户可以有很多爱好,这些爱好被组织成不同的爱好组。
所以我有 4 个相关的 tables: users, users_hobbies, 爱好, hobby_groups.
用户是 has-and-belongs-to-many 与爱好的关系,通过 users_hobbies 加入 table。
爱好 belongs-to 一个 hobby_group, hobby_group has-many 爱好
有道理,到目前为止非常简单。
在 UsersHobbiesController 中,我有:
$paginate = [
'contain' => [
'Hobby' => [
'fields' => ['id', 'name'],
'HobbyGroup' => [
'fields' => ['id', 'name']
]
]
]
];
此外,在我的 index() 函数中,我构建了分页。
$usersHobbies = $this->paginate('UsersHobby');
$this->set(compact('usersHobbies));
当我访问我的 index.ctp 视图文件中的 $usersHobbies 变量时,它具有我想要构建输出 table 的数据。看起来像:
array(
(int) 0 => array(
'UsersHobby' => array(...),
'Hobby' => array(
'id' => 'abc-def-ghi',
'name' => 'Jet Skiing',
'HobbyGroup' => array(
'id' => 'oiuy-trew-qldf',
'name' => 'Watersports'
)
)
)
....
)
为了对输出 table 进行排序,我添加了一些排序列:
<th><?php echo $this->Paginator->sort('Hobby.name', 'Hobby'); ?></th>
<th><?php echo $this->Paginator->sort('Hobby.HobbyGroup.id', 'Hobby'); ?></th>
第一个 header 用于对爱好名称进行排序。但是我不能得到第二个header来为HobbyGroup排序。有没有简单的方法可以做到这一点?
我在 Whosebug 上搜索了几个小时,但似乎找不到适合我的答案。谢谢
由于 CakePHP 获取数据的方式,这不会像您预期的那样工作。
根据你建立关系的方式,Cake 会先 select 爱好然后然后 做另一个查询兴趣小组。
因此,当该数据映射到爱好列表时,您应用于第二个查询的任何排序通常都是无用的并且会丢失。
所以你有
SELECT hobbies....
然后再发一个select
SELECT hooby_groups WHERE hobby_id IN [list of ids ] ORDER BY hobby_groups_id
第二个select的数据会映射到第一个,所以你的order by并没有做太多!
根据您使用的 CakePHP 版本,您可以做几件事:
定义关系以使用 INNER JOIN
策略,这样将避免创建两个 SELECT
语句。这样 order by
原因将按照您的预期对所有数据进行排序。需要注意的是,INNER JOIN
没有任何关联组的兴趣爱好永远不会被您的分页 select 编辑。
如果您使用的是 CakePHP 2.x,您可以查看 Custom Query Pagination 并根据需要构建查询以使其正常工作。
如果您使用的是 CakePHP 3.x,您那里有一个查询生成器,分页器可以对任何查询进行分页,因此您可以在那里进行内部联接。
为了帮助您解决问题,您可以使用 CakePHP 中的 DebugKit
查看实际查询是什么 运行 以及调整这个和那个参数如何影响查询的生成方式。您将看到应用 order by
的位置以及它可能不起作用的原因。
在 CakePHP 2.x 中,您可以使用 type
来控制连接的完成方式。您需要使用 INNER
这是一个用于跟踪用户爱好的简单应用程序。一个用户可以有很多爱好,这些爱好被组织成不同的爱好组。
所以我有 4 个相关的 tables: users, users_hobbies, 爱好, hobby_groups.
用户是 has-and-belongs-to-many 与爱好的关系,通过 users_hobbies 加入 table。 爱好 belongs-to 一个 hobby_group, hobby_group has-many 爱好
有道理,到目前为止非常简单。
在 UsersHobbiesController 中,我有:
$paginate = [
'contain' => [
'Hobby' => [
'fields' => ['id', 'name'],
'HobbyGroup' => [
'fields' => ['id', 'name']
]
]
]
];
此外,在我的 index() 函数中,我构建了分页。
$usersHobbies = $this->paginate('UsersHobby');
$this->set(compact('usersHobbies));
当我访问我的 index.ctp 视图文件中的 $usersHobbies 变量时,它具有我想要构建输出 table 的数据。看起来像:
array(
(int) 0 => array(
'UsersHobby' => array(...),
'Hobby' => array(
'id' => 'abc-def-ghi',
'name' => 'Jet Skiing',
'HobbyGroup' => array(
'id' => 'oiuy-trew-qldf',
'name' => 'Watersports'
)
)
)
....
)
为了对输出 table 进行排序,我添加了一些排序列:
<th><?php echo $this->Paginator->sort('Hobby.name', 'Hobby'); ?></th>
<th><?php echo $this->Paginator->sort('Hobby.HobbyGroup.id', 'Hobby'); ?></th>
第一个 header 用于对爱好名称进行排序。但是我不能得到第二个header来为HobbyGroup排序。有没有简单的方法可以做到这一点?
我在 Whosebug 上搜索了几个小时,但似乎找不到适合我的答案。谢谢
由于 CakePHP 获取数据的方式,这不会像您预期的那样工作。
根据你建立关系的方式,Cake 会先 select 爱好然后然后 做另一个查询兴趣小组。
因此,当该数据映射到爱好列表时,您应用于第二个查询的任何排序通常都是无用的并且会丢失。
所以你有
SELECT hobbies....
然后再发一个select
SELECT hooby_groups WHERE hobby_id IN [list of ids ] ORDER BY hobby_groups_id
第二个select的数据会映射到第一个,所以你的order by并没有做太多!
根据您使用的 CakePHP 版本,您可以做几件事:
定义关系以使用
INNER JOIN
策略,这样将避免创建两个SELECT
语句。这样order by
原因将按照您的预期对所有数据进行排序。需要注意的是,INNER JOIN
没有任何关联组的兴趣爱好永远不会被您的分页 select 编辑。如果您使用的是 CakePHP 2.x,您可以查看 Custom Query Pagination 并根据需要构建查询以使其正常工作。
如果您使用的是 CakePHP 3.x,您那里有一个查询生成器,分页器可以对任何查询进行分页,因此您可以在那里进行内部联接。
为了帮助您解决问题,您可以使用 CakePHP 中的 DebugKit
查看实际查询是什么 运行 以及调整这个和那个参数如何影响查询的生成方式。您将看到应用 order by
的位置以及它可能不起作用的原因。
在 CakePHP 2.x 中,您可以使用 type
来控制连接的完成方式。您需要使用 INNER