不可否认Cakephp对于查询的封装是有限制的,但是通过利用Cakephp的语法规则,可以很好的弥补这一点。
我们在应用中遇到的问题:
{查询Note的ID小于10的所有User,User表和Note表是一对多关联}
我们通常的做法是
1.
$users = $this->User->find('all',array(
2.
'conditions' => array(
3.
'Note.id <' => 10
4.
)
5.
));
注意:这种做法是错误的。
原因是:
Cakephp对于hasMany的关联,会生成下列的语句
1.
SELECT `User`.`id`, `User`.`name`, `User`.`username`, `User`.`password`, `User`.`created` FROM `users` AS `User` WHERE `Note`.`id` < 10
可以看到,Note表并没有被Join到查询中,所以,MySql会提示
1.
Unknown column 'Note.id' in 'where clause'
我们应该怎样查询条件从属于关联表的记录呢?
简单介绍一下Cakephp的四种关联模式对应的从属关联条件的方法。
1. 最简单的hasOne和belongsTo关联
这类的关联我们可以直接写关联表的条件,而不会出现Unknow column的错误。
2. 稍稍复杂的hasMany关联(一对多关联)
就像你在上面看见的,hasMany关联是不能直接实现上述的查询条件的,但是我们可以变通一下,我们可以把hasMany关联查询转换为belongsTo关联查询,按照上面的条件,我们再试一试
01.
$users = $this->User->Note->find('all',array(
02.
'conditions' => array(
03.
'Note.id <' => 10
04.
),
05.
'contain' => array('User'),
06.
'fields' => array(
07.
'Note.id',
08.
'User.id',
09.
'User.name'
10.
)
11.
));
这次得到的结果类似于下面的数据
01.
Array
02.
(
03.
[0] => Array
04.
(
05.
[Note] => Array
06.
(
07.
[id] => 1
08.
)
09.
[User] => Array
10.
(
11.
[id] => 54
12.
[name] => Cole Cox
13.
)
14.
)
15.
[1] => Array
16.
(
17.
[Note] => Array
18.
(
19.
[id] => 2
20.
)
21.
[User] => Array
22.
(
23.
[id] => 81
24.
[name] => Vincent Cobb
25.
)
26.
)
27.
)
OK,这就是我们想要的!
同样的方法还可以{查找一个User的所有Friend},请看下面的部分。。。
3. 不太好理解的hasAndBelongsToMany关联(多对多关联)
我们的数据表结构如下
01.
--用户表
02.
03.
CREATE TABLE IF NOT EXISTS `users` (
04.
`id` int(11) NOT NULL auto_increment,
05.
`name` varchar(60) collate utf8_unicode_ci NOT NULL,
06.
`username` varchar(20) collate utf8_unicode_ci NOT NULL,
07.
`password` varchar(255) collate utf8_unicode_ci NOT NULL,
08.
`created` datetime NOT NULL,
09.
PRIMARY KEY (`id`)
10.
) ENGINE=MyISAM;
11.
12.
--用户和好友关联表
13.
14.
CREATE TABLE IF NOT EXISTS `friends_users` (
15.
`id` bigint(10) NOT NULL auto_increment,
16.
`user_id` bigint(10) NOT NULL,
17.
`friend_id` bigint(10) NOT NULL,
18.
PRIMARY KEY (`id`)
19.
) ENGINE=MyISAM;
我们需要建立三个模型类
User模型,对应于users表,文件/app/models/user.php
1.
class User extends AppModel{
2.
var $name = 'User';
3.
4.
var $hasAndBelongsToMany = array(
5.
'Friend' => array('with' => 'FriendsUser')
6.
);
7.
8.
}
Friend模型,也对应users表(Friend和User共享数据),用来和users模型进行多对多关联
文件/app/models/friend.php
1.
class Friend extends AppModel {
2.
var $name = 'Friend';
3.
var $useTable = 'users';
4.
var $hasAndBelongsTo = array(
5.
'User' => array('with' => 'FriendsUser')
6.
);
7.
}
FriendsUser模型,对应关联表friends_users,文件/app/models/friends_user.php
1.
class FriendsUser extends AppModel {
2.
var $name = 'FriendsUser';
3.
var $belongsTo = array('Friend','User');
4.
}
好了,定义好模型,我们要查询User的所有Friend,在控制器中,要这样
01.
class UsersController extends AppController {
02.
var $name = 'Users';
03.
04.
//这里,我们要引入这三个模型,如果你有更多的模型,可以一起引入
05.
var $uses = array('User','Friend','FriendsUser');
06.
07.
function test(){
08.
$conditions = array(
09.
'User.id' => 1
10.
);
11.
$contain = array('User','Friend');
12.
$fields = array(
13.
'User.id',
14.
'User.name',
15.
'Friend.id',
16.
'Friend.name'
17.
);
18.
$limit = 5;
19.
20.
//我们使用了中间表FriendsUser,来查询,compact函数是cakephp提倡的用法
21.
$data = $this->FriendsUser->find('all',compact(
22.
'conditions',
23.
'contain',
24.
'fields',
25.
'limit'
26.
));
27.
28.
debug($data);
29.
exit;
30.
}
31.
}
查询的结果,可能类似下面的数据
01.
Array
02.
(
03.
[0] => Array
04.
(
05.
[User] => Array
06.
(
07.
[id] => 1
08.
[name] => Drake Duran
09.
)
10.
11.
[Friend] => Array
12.
(
13.
[id] => 2
14.
[name] => Dane Knowles
15.
)
16.
17.
)
18.
19.
[1] => Array
20.
(
21.
[User] => Array
22.
(
23.
[id] => 1
24.
[name] => Drake Duran
25.
)
26.
27.
[Friend] => Array
28.
(
29.
[id] => 3
30.
[name] => Felix Kelley
31.
)
32.
33.
)
34.
35.
)
可以看到,这正是我们需要的数据。
总结一下
Cakephp关联表的从表查询,可以借助belongsTo关联来查询,只要我们做好模型的相互关联,查询是没有问题的!
本文深入探讨了CakePHP框架中查询优化技巧,特别针对如何通过修改关联查询方式来解决查询条件从属于关联表的问题。通过实例演示了如何在一对多关联场景下,使用CakePHP的belongsTo关联来获取所需数据,并介绍了复杂如多对多关联的查询方法。此外,文章还展示了如何在控制器中灵活引入多个模型进行联合查询,最终实现高效且准确的数据检索。

1344

被折叠的 条评论
为什么被折叠?



