yii 关系查询详解

/******  
 1, 声明关系  
 *****/  
 
 为了使用关系型 AR,我们建议在需要关联的表中定义主键-外键约束。这些约束可以帮助保证相关数据的一致性和完整性。 

在 AR 中,有四种关系:  
 
 BELONGS_TO(属于): 如果表 A 和 B 之间的关系是一对多,则 表 B 属于 表 A (例如 Post 属于 User);  
 HAS_MANY(有多个): 如果表 A 和 B 之间的关系是一对多,则 A 有多个 B (例如 User 有多个 Post);  
 HAS_ONE(有一个): 这是 HAS_MANY 的一个特例,A 最多有一个 B (例如 User 最多有一个 Profile);  
 MANY_MANY: 这个对应于数据库中的 多对多 关系。  

由于多数 DBMS 不直接支持 多对多 关系,因此需要有一个关联表将 多对多 关系分割为 一对多 关系。   
 
 在我们的示例数据结构中,tbl_post_category 就是用于此目的的。  
 在 AR 术语中,我们可以解释 MANY_MANY 为 BELONGS_TO 和 HAS_MANY 的组合。   
 例如,Post 属于多个(belongs to many) Category ,Category 有多个(has many) Post.  
 
 AR 中定义关系需要覆盖 CActiveRecord 中的 relations() 方法。  
 
 此方法返回一个关系配置数组。每个数组元素通过如下格式表示一个单一的关系。  
 
 'VarName'=>array('RelationType', 'ClassName', 'ForeignKey', ...additional options)  
 
 其中 VarName 是关系的名字;  
 RelationType 指定关系类型,可以是一下四个常量之一:   
 self::BELONGS_TO  
 self::HAS_ONE  
 self::HAS_MANY  
 self::MANY_MANY  
 
 ClassName 是此 AR 类所关联的 AR 类的名字;   
 ForeignKey 指定关系中使用的外键(一个或多个)。  
 
 额外的选项可以在每个关系的最后指定(稍后详述)。  
 
 class Post extends CActiveRecord  
 {  
     ......  
    
     public function relations()  
     {  
         return array(  
             'author'=>array(self::BELONGS_TO, 'User', 'author_id'),  
             'categories'=>array(self::MANY_MANY, 'Category', 'tbl_post_category(post_id, category_id)'),  
         );  
     }  
 } 

信息: 外键可能是复合的,包含两个或更多个列。   
 这种情况下,我们应该将这些外键名字链接,中间用空格或逗号分割。  
 对于 MANY_MANY 关系类型, 关联表的名字必须也必须在外键中指定。  
 例如, Post 中的 categories 关系由外键 tbl_post_category(post_id, category_id) 指定。  
 
 AR 类中的关系定义为每个关系向类中隐式添加了一个属性。  
 在一个关系查询执行后,相应的属性将将被以关联的 AR 实例填充。   
 例如,如果 $author 代表一个 User AR 实例, 我们可以使用 $author->posts 访问其关联的 Post 实例。  
 
 /*****  
 
 2, 执行关系查询  
 
 ******/  
    
 执行关系查询最简单的方法是读取一个 AR 实例中的关联属性。  
 如果此属性以前没有被访问过,则一个关系查询将被初始化,它将两个表关联并使用当前 AR 实例的主键过滤。  
 查询结果将以所关联 AR 类的实例的方式保存到属性中。  
 这就是传说中的 懒惰式加载(lazy loading,也可译为 迟加载) 方式,例如,关系查询只在关联的对象首次被访问时执行。   
 
 下面的例子演示了怎样使用这种方式:  
 // 获取 ID 为 10 的帖子  
 $post=Post::model()->findByPk(10);  
 // 获取帖子的作者(author): 此处将执行一个关系查询。  
 $author=$post->author;  
 
 信息: 如果关系中没有相关的实例,则相应的属性将为 null 或一个空数组。   
 BELONGS_TO 和 HAS_ONE 关系的结果是 null, HAS_MANY 和 MANY_MANY 的结果是一个空数组。   
 
 注意, "HAS_MANY 和 MANY_MANY 关系返回对象数组,你需要在访问任何属性之前先遍历这些结果。"   
 否则,你可能会收到 "Trying to get property of non-object(尝试访问非对象的属性)" 错误。  
 
 懒惰式加载用起来很方便,但在某些情况下并不高效。  
 如果我们想获取 N 个帖子的作者,使用这种懒惰式加载将会导致执行 N 个关系查询。  
 
    
 这种情况下,我们应该改为使用 渴求式加载(eager loading)方式。  
 渴求式加载方式会在获取主 AR 实例的同时获取关联的 AR 实例。   
 这是通过在使用 AR 中的 find 或 findAll 方法时配合使用 with 方法完成的。  
 
 例如:  
 $posts=Post::model()->with('author')->findAll();  
 上述代码将返回一个 Post 实例的数组。  
 与懒惰式加载方式不同,在我们访问每个 Post 实例中的 author 属性之前,它就已经被关联的 User 实例填充了。   
 渴求式加载通过 一个 关系查询返回所有帖子及其作者,而不是对每个帖子执行一次关系查询。  

你可能感兴趣的:(yii 关系查询详解)