我们已经了解了怎样通过AR从单个数据表中获取数据,那么如果要关联多个数据表,AR又应该怎样操作列
我们看到,在 创建的AR模型User类里面有一个relations方法,它就是用来返回与当前表关联关系的
一、声明关系
要想在AR中使用关联查询,我们需要先申明user表与其他表的关联关系
AR中有四中关联关系,
BELONGS_TO(属于):比如,一个用户(user)只有一个城市id(city_id),但是一个城市id下面有多个用户,那么用户表就属于城市表,简单的表述就是 A表的多行数据对应B表的一行数据
HAS_MANY(有多个):比如,一个城市对应多个用户,那么城市表就有多个用户表
HAS_ONE(有一个):比如,一个用户只有一个用户简介,那么用户表就有一个用户简介表
MANY_MANY(多对多):比如,一个商家有多个分店,一个商品支持多个分店使用,那么需要一个中间表把商家的分店和商品关联起来,比如商品表Groupon,分店表shop,那么groupon_shop表用来存放商品和分店的关联关系
他们分别代表这几个类
const BELONGS_TO='CBelongsToRelation';
const HAS_ONE='CHasOneRelation';
const HAS_MANY='CHasManyRelation';
const MANY_MANY='CManyManyRelation';
const STAT='CStatRelation';
那么具体怎么去申明列
我们拿user表和city表来做个实例,根据刚才的判断,我们使用Belongs to来定义
先用gii生成一个City模型
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'city'=>array(self::BELONGS_TO,'City','city_id'),
);
}
索引下表city是这个关联关系的名字,是自定义的,在后面调用$user->city可以获取到city表对应的数据
数组的第一个参数是 关系申明
第二个参数是关联的 AR模型
第三个参数是关联的外键名,
如果还需要设置其他的参数,可以在第四个参数用一个数组来设置,具体的可设置的参数参考 关联关系对应的四个类
二、单条语句使用关联查询
1.AR的关联查询支持 延迟加载和饥渴似加载两种
我们先来看延迟加载
在新建一个方法actionRelation
先找出user对象
public function actionRelation($id){
$id = trim($id);
//懒惰加载
$user = User::model()->findByPk($id);
//此时的user对象的related属性是一个空数组,user对象的打印结果如下图
dump($user);
// $city = $user->city;
// dump($city);
}
![](http://static.oschina.net/uploads/space/2013/1012/125655_tJiE_1165126.png)
再调用user对象里面的city关联属性
public function actionRelation($id){
$id = trim($id);
//懒惰加载
$user = User : : model() - > findByPk($id);
//此时的user对象的related属性是一个空数组,user对象的打印结果如下图
// dump($user);
//获取与user对象相关联的city对象,调用city属性的时候,会调用relations方法里面city对应的 关联关系 找到city对象
$city = $user - > city;
//打印结果见下图
dump($city);
![](http://static.oschina.net/uploads/space/2013/1012/125755_Uc0g_1165126.png)
当调用一次city属性之后,延迟加载了city对象 user对象的related属性添加了city对象值
public function actionRelation($id){
$id = trim($id);
//懒惰加载
$user = User::model()->findByPk($id);
//此时的user对象的related属性是一个空数组,user对象的打印结果如下图
// dump($user);
//获取与user对象相关联的city对象,调用city属性的时候,会调用relations方法里面city对应的 关联关系 找到city对象
$city = $user->city;
// dump($city);
//此时我们再打印user对象,related属性就不是一个空数组了,打印结果如下图
dump($user,false);
//我们可以像调用user属性一样去调用city对象的属性,比如我想获取城市名
dump($city->name);
}
![](http://static.oschina.net/uploads/space/2013/1012/125949_5Mhi_1165126.png)
从数据库的角度来说,延迟加载就相当于先查询user表,然后根据city_id查询city表对应的数据
我们再来看看饥渴式加载
//饥渴式加载我们使用到关键词with在find之前
public function actionEager($id){
$id = trim($id);
//饥渴式加载
$user = User::model()->with('city')->findByPk($id);
dump($user);
}
![](http://static.oschina.net/uploads/space/2013/1012/130144_qkrU_1165126.png)
我们看到打印结果,如果使用with关键词之后,默认就已经将city表对应数据加载到user对象的related属性中
//饥渴式加载我们使用到关键词with在find之前
public function actionEager($id){
$id = trim($id);
//饥渴式加载
$user = User::model()->with('city')->findByPk($id);
// dump($user);
//获取城市名称
$name = $user->city->name;
//打印结果如下
dump($name);
}
'广州'
我们看到 当调用$user->city的时候 获取的就是对应的city对象
从数据库的角度来说 饥渴式加载 就相当于join查询user和city两张表 默认的join类型是left join左联查询
我们知道一张表可能会与多个表发生关联关系,比如 又来一张 user_info 表(用户信息表),user_info表里面有一个外键user_id关联表的id,而且user与user_info是一一对应的关系,那么在使用AR关联时,只需要在relations方法里面添加一个user_info
user_info表 建表语句
CREATE TABLE `user_info` (
`id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL default '0' COMMENT '用户ID',
`info` text character set utf8 NOT NULL COMMENT '简介',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='用户信息表
//添加一个user_info 的关联关系
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'city'=>array(self::BELONGS_TO,'City','city_id'),
'user_info'=>array(self::HAS_ONE,'UserInfo','user_id'),
);
}
在饥渴式加载中如下使用,with方法中添加一个参数user_info即可
public function actionEager($id){
$id = trim($id);
//饥渴式加载
$user = User::model()->with('city','user_info')->findByPk($id);
dump($user);
}
打印结果如下图,可以看到city对象与user_info对象都已经加载到user对象的related属性中了
![](http://static.oschina.net/uploads/space/2013/1012/130430_HF6q_1165126.png)