十八、AR数据库的关联查询relations之单条数据查询

我们已经了解了怎样通过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);
    }


再调用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);

当调用一次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);
    }


从数据库的角度来说,延迟加载就相当于先查询user表,然后根据city_id查询city表对应的数据
 
我们再来看看饥渴式加载

     //饥渴式加载我们使用到关键词with在find之前
public function actionEager($id){
        $id = trim($id);
        //饥渴式加载
        $user = User::model()->with('city')->findByPk($id);
        dump($user);
    }

我们看到打印结果,如果使用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属性中了

转载于:https://my.oschina.net/lonxom/blog/168257

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值