Cakephp多表关联的从表查询笔记

edited 十月 2013 in CakePHP
不可否认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

原始討論: http://twpug.net/x/modules/newbb/viewtopic.php?topic_id=4177
Sign In or Register to comment.