不可否认Cakephp对于查询的封装是有限制的,但是通过利用Cakephp的语法规则,可以很好的弥补这一点。
我们在应用中遇到的问题:
{查询Note的ID小于10的所有User,User表和Note表是一对多关联}
我们通常的做法是
$users = $this->User->find('all',array(
'conditions' => array(
'Note.id <' => 10
)
));
注意:这种做法是错误的。
原因是:
Cakephp对于hasMany的关联,会生成下列的语句
SELECT `User`.`id`, `User`.`name`, `User`.`username`, `User`.`password`, `User`.`created` FROM `users` AS `User` WHERE `Note`.`id` < 10
可以看到,Note表并没有被Join到查询中,所以,MySql会提示
Unknown column 'Note.id' in 'where clause'
我们应该怎样查询条件从属于关联表的记录呢?
简单介绍一下Cakephp的四种关联模式对应的从属关联条件的方法。
1. 最简单的hasOne和belongsTo关联
这类的关联我们可以直接写关联表的条件,而不会出现Unknow column的错误。
2. 稍稍复杂的hasMany关联(一对多关联)
就像你在上面看见的,hasMany关联是不能直接实现上述的查询条件的,但是我们可以变通一下,我们可以把hasMany关联查询转换为belongsTo关联查询,按照上面的条件,我们再试一试
$users = $this->User->Note->find('all',array(
'conditions' => array(
'Note.id <' => 10
),
'contain' => array('User'),
'fields' => array(
'Note.id',
'User.id',
'User.name'
)
));
这次得到的结果类似于下面的数据
Array
(
[0] => Array
(
[Note] => Array
(
[id] => 1
)
[User] => Array
(
[id] => 54
[name] => Cole Cox
)
)
[1] => Array
(
[Note] => Array
(
[id] => 2
)
[User] => Array
(
[id] => 81
[name] => Vincent Cobb
)
)
)
OK,这就是我们想要的!
同样的方法还可以{查找一个User的所有Friend},请看下面的部分。。。
3. 不太好理解的hasAndBelongsToMany关联(多对多关联)
我们的数据表结构如下
--用户表
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(60) collate utf8_unicode_ci NOT NULL,
`username` varchar(20) collate utf8_unicode_ci NOT NULL,
`password` varchar(255) collate utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
--用户和好友关联表
CREATE TABLE IF NOT EXISTS `friends_users` (
`id` bigint(10) NOT NULL auto_increment,
`user_id` bigint(10) NOT NULL,
`friend_id` bigint(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
我们需要建立三个模型类
User模型,对应于users表,文件/app/models/user.php
class User extends AppModel{
var $name = 'User';
var $hasAndBelongsToMany = array(
'Friend' => array('with' => 'FriendsUser')
);
}
Friend模型,也对应users表(Friend和User共享数据),用来和users模型进行多对多关联
文件/app/models/friend.php
class Friend extends AppModel {
var $name = 'Friend';
var $useTable = 'users';
var $hasAndBelongsTo = array(
'User' => array('with' => 'FriendsUser')
);
}
FriendsUser模型,对应关联表friends_users,文件/app/models/friends_user.php
class FriendsUser extends AppModel {
var $name = 'FriendsUser';
var $belongsTo = array('Friend','User');
}
好了,定义好模型,我们要查询User的所有Friend,在控制器中,要这样
class UsersController extends AppController {
var $name = 'Users';
//这里,我们要引入这三个模型,如果你有更多的模型,可以一起引入
var $uses = array('User','Friend','FriendsUser');
function test(){
$conditions = array(
'User.id' => 1
);
$contain = array('User','Friend');
$fields = array(
'User.id',
'User.name',
'Friend.id',
'Friend.name'
);
$limit = 5;
//我们使用了中间表FriendsUser,来查询,compact函数是cakephp提倡的用法
$data = $this->FriendsUser->find('all',compact(
'conditions',
'contain',
'fields',
'limit'
));
debug($data);
exit;
}
}
查询的结果,可能类似下面的数据
Array
(
[0] => Array
(
[User] => Array
(
[id] => 1
[name] => Drake Duran
)
[Friend] => Array
(
[id] => 2
[name] => Dane Knowles
)
)
[1] => Array
(
[User] => Array
(
[id] => 1
[name] => Drake Duran
)
[Friend] => Array
(
[id] => 3
[name] => Felix Kelley
)
)
)
可以看到,这正是我们需要的数据。
总结一下
Cakephp关联表的从表查询,可以借助belongsTo关联来查询,只要我们做好模型的相互关联,查询是没有问题的!
原文地址为:
http://www.thinkly.cn/index.php/archives/187