本文主要是介绍Yii框架relations的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
通过在 relations() 中声明这些相关对象,我们就可以利用强大的 Relational ActiveRecord (RAR) 功能来访问资讯的相关对象,例如它的作者和评论。不需要自己写复杂的 SQL JOIN 语句。
前提条件
在组织数据库时,需要使用主键与外键约束才能使用ActiveReocrd的关系操作;
场景
申明关系
两张表之间的关系无非三种:一对多;一对一;多对多; 在AR中,定义了四种关系:
关系 定义
BELONGS_TO A和B的关系是一对多,那么B属于A
HAS_MANY A和B之间的关系是一对多,那么A有多个B
HAS_ONE 这是HAS_MANY的一种特殊情况,A至多有一个B
MANY_MANY 这个对应多对多的情况,在AR里会将多对多以BELONGS_TO和HAS_MANY的组合来解释
在AR中通过重写CActiveRecord类的relations()方法来申明关系;这个方法返回一个关系配置的数组;一个数组无素代表一个单独的关系,格式如下:
‘VarName’=>array(‘RelationType’,’ClassName’,’ForeignKey’, …additional options)
Var Name 关系名
Relation Type 四种关系:self::BELONGS_TO, self::HAS_ONE, self::HAS_MANY, self::MANY_MANY
Class Name 代表当前AR类要关联的那个AR类名
Foreign Key 实现关系的外键, 有可能有多个,即列名
‘select’: string|array, 被选中的列列表。默认值为 ‘*’,这意味着是所有列。 如果它们出现在一个表达式中(例如: COUNT(relationName.name) AS name_count)。
‘condition’: string, WHERE子句。 默认值为空。 注意,列引用需要加入’relationName’前缀 。(例如:relationName.age>20)
‘order’: string, ORDER BY子句。 默认值为空。 注意,列引用需要加入’relationName’前缀 。(例如:relationName.age DESC)
‘with’: string|array, 应该与这个对象一起装载的子对象相关名单。 注意,这仅仅是延迟加载,而不是预先加载。
‘joinType’: 联接类型。 默认值为‘LEFT OUTER JOIN’。
‘alias’: 关系与关联表的别名。 它默认为null, 意味着表的别名与关系名称相同。
‘params’: 参数绑定到要生成的SQL语句上。 这应作为名称-值的数组。
‘on’: ON 子句。 此处指定的条件将追加到使用 AND 运算符的联接条件。
‘index’: 其值应作为存储相关的对象的数组的键的列的名称。 此选项仅适用于, HAS_MANY 和 MANY_MANY 关系。
‘scopes’: 应用范围。在单一的范围情况下可以像’scopes’=>’scopeName’, 在多个作用域范围情况下可以使用数组像这样’scopes’=>array(‘scopeName1’,’scopeName2’)。
延迟加载时有一定的关系,下列选项可用:
‘group’: string, GROUP BY子句。 默认值为空。 注意,列引用需要加入’relationName’前缀 。(例如: relationName.age)。此选项仅适用于HAS_MANY 和 MANY_MANY 关系。
‘having’: string, HAVING子句。 默认值为空。 注意,列引用需要加入’relationName’前缀 。(例如: relationName.age)。此选项仅适用于HAS_MANY 和 MANY_MANY 关系。
‘limit’: 数据行的limit选择。 这个选项不能应用到BELONGS_TO。
‘offset’: 数据行的偏移量。 这个选项不能应用到BELONGS_TO。
‘through’: 获取相关的数据时将用作桥的模型的关系的名称。可以设置仅为 HAS_ONE 和 HAS_MANY。
return array(
'reply' => array(self::BELONGS_TO, 'BookPostReply', 'postid'),//连接BookPostReply表
);
self::BELONGS_TO默认是用当前指定的键跟关联表的主键进行join
默认生成的sql是 on id = postid,id是BookPostReply的主键。
需要生成 on BookPostReply.postid = t.postid,不去关联主键,而且关联其中一个字段的值
return array(
'reply' => array(self::BELONGS_TO, 'BookPostReply', '', 'on' => 't.postid=reply.postid'),
);
关联中的东西也可以有order的
'imgs'=>array(self::HAS_MANY,"LightProImgs","pid","order"=>"imgs.paixu desc","limit"=>3)
多表关联的实际应用:
1,首先多表关联是在models/xx.php的relations里配置的。而且是互配,但有区别。
格式:
‘VarName’=>array(‘RelationType’, ‘ClassName’, ‘ForeignKey’, …additional options)
需要弄清楚的几点:
1,VarName指什么? 详见下面例2。
2,RelationType。一共有4种,分别为self::HAS_MANY, self::BELONGS_TO, self::MANY_MANY, self::HAS_ONE。
3,ClassName。即关联的另一个../model/类名.php。
4,ForeignKey。谁是谁的外键?写了是用主键关联,为空两个表不是用主键关联需要on
5,附加条件
两个表不是用主键关联
‘user’ => array(self::BELONGS_TO, ‘OaskUser’, ” ,’on’=>’name=userName’ , ‘select’=>’TrueName’, ‘order’=>’sort asc’),
'varchar'=>array(self::HAS_ONE, 'CustomerEntityVarchar', 'entity_id','select'=>'varchar.value','on'=>'varchar.attribute_id="831"'),
BELONGS_TO(属于): 如果表 A 和 B 之间的关系是一对多,则 表 B 属于 表 A ;
HAS_MANY(有多个): 如果表 A 和 B 之间的关系是一对多,则 A 有多个 B ;
HAS_ONE(有一个): 这是 HAS_MANY 的一个特例,A 最多有一个 B ;
MANY_MANY: 这个对应于数据库中的多对多关系。 由于多数 DBMS 不直接支持 多对多 关系,因此需要有一个关联表将多对多关系分割为一对多关系。在 AR术语中,我们可以解释 MANY_MANY 为 BELONGS_TO 和 HAS_MANY 的组合。
STAT :除了上述的关系类型,一个特殊的关系,称为STAT也支持 可用于进行统计查询(或聚合查询) 。 检索聚合对相关对象的信息,如数量。如 一篇日志共有多少个评论
'detailCounts' => array(self::STAT, 'PurchaseDetail', 'purchase_hid'),
例1,一对多关系 (post和user之间的关系)
(1)models/Post.php
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)'),);}
}
其中Post与User的关系是BELONGS_TO(多对一)关系,并通过Post的author_id与User关联。Post中author_id是外键,关联到User中。注:此处的VarName是author,一个对象 。
(2)models/User.php
class User extends CActiveRecord
{......public function relations(){return array('posts'=>array(self::HAS_MANY, 'Post', 'author_id'),);}
}
对于User,与Post的关系是属于HAS_MANY(一对多)关系。并通过Post的author_id与Post关联。 由于两者是一对多关系,所以要用posts
例2,多对多关系。中间表名( 本表外键, many表外键 )
在FailParts.php中
'Users' => array(self::MANY_MANY, 'User', 'fail_parts_user(fail_parts_id, user_id)'),
在User.php中
'FailParts' => array(self::MANY_MANY, 'FailParts', 'fail_parts_user(user_id, fail_parts_id)'),
由于两者是多对多关系,所以要用Users ,而不是User;要用FailParts,而不是FailPart。此处的Users和FailParts,即为前面的VarName。
例3,一对一关系。比较简单,暂略。
2,关于VarName。
对于类A.php,’VarName’=>array(‘RelationType’, ‘B’, ‘ForeignKey’, …additional options)
其中VarName与B基本相同。但未必完全一样。此时就可以在A的views/A/xx.php中通过VarName来访问B及其属性值了。
如果是一对一/一对多:A->VarName->name
如果是多对多:
$users = As->VarName
foreach($users as $u){$_tmp_users[] = $u -> getName;
}
userStr = implode(', ', $_tmp_users);
懒惰式加载(lazy loading,也可译为 迟加载) 方式
// 获取 ID 为 10 的帖子
$post=Post::model()->findByPk(10);
// 获取帖子的作者(author): 此处将执行一个关联查询。
$author=$post->author;
懒惰式加载用起来很方便,但在某些情况下并不高效。
渴求式加载(eager loading)方式。$posts=Post::model()->with(‘author’,’categories’)->findAll();
AR scopes
//SchoolDepartment::model()->allDepartmentAndClass($id)->findAll();
public function relations() {return array('class' => array(self::HAS_MANY, 'SchoolClass', 'school_department_id'),);
}public function scopes() {return array('allDepartmentAndClass',);
}public function allDepartmentAndClass($id) {$this->getDbCriteria()->mergeWith(array('with' => "class",'condition' => "t.tbl_school_id=$id",));return $this;
}
强制查询使用join连接查询
$criteria->together = true;
下面介绍是一种“急切导入”方法:在使用find和findAll时,使用with()方法,例:
$posts=Post::model()->with('author')->findAll()
$posts=Post::model()->with('author')->findAll()
这样就可以在一次查询时连同查询其他信息了;with方法可以接受多个关系:
$posts=Post::model()->with('author','categories')->findAll();
$posts=Post::model()->with('author','categories')->findAll();
这样就可以将作者和类别的信息一并进行查询;同样,with还支持多重急切导入
$posts=Post::model()->with( 'author.profile', 'author.posts', 'categories')->findAll();
http://blog.csdn.net/xinqingch/article/details/8219330
http://hudeyong926.iteye.com/blog/1274077
这篇关于Yii框架relations的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!