이 글에서는 주로 YII 상관 쿼리 관련 정보를 소개합니다. 필요한 친구들은 참고하시면 됩니다
1. 다중 테이블 상관 관계 구성
AR을 사용하여 상관 쿼리를 수행하기 전에 먼저 해야 할 일 AR은 하나의 AR 클래스가 다른 AR 클래스와 어떻게 관련되어 있는지 알고 있습니다.
두 AR 클래스 간의 관계는 AR 클래스가 표현하는 데이터 테이블 간의 관계를 통해 직접적으로 연관됩니다. 데이터베이스 관점에서 테이블 A와 B 사이에는 일대다(예: tbl_user 및 tbl_post), 일대일(예: tbl_user 및 tbl_profile) 및 다대다(예: 다대다) 관계의 세 가지 유형이 있습니다. tbl_category 및 tbl_post와 같은 다대다). AR에는 네 가지 종류의 관계가 있습니다.
BELONGS_TO(속함): 테이블 A와 B 간의 관계가 일대다인 경우 테이블 B는 테이블 A에 속합니다(예: Post는 사용자에 속함).
HAS_MANY(여러 개 있음): 테이블 A와 B 사이의 관계가 일대다인 경우 A에는 여러 개의 B가 있습니다(예: 사용자에게 여러 개의 게시물이 있음).
HAS_ONE(하나 있음): HAS_MANY의 특수한 경우, A에는 최대 하나의 B가 있습니다(예: 사용자는 최대 하나의 프로필을 가집니다).
MANY_MANY: 이는 데이터베이스의 다대다 관계에 해당합니다. 대부분의 DBMS는 다대다 관계를 직접 지원하지 않기 때문에 다대다 관계를 일대다 관계로 분할하려면 관계 테이블이 필요합니다. 예제 데이터 구조에서는 tbl_post_category가 이 목적으로 사용됩니다. AR 용어로 MANY_MANY를 BELONGS_TO와 HAS_MANY의 조합으로 해석할 수 있습니다. 예를 들어 Post는 Many(belongs to Many) 카테고리에 속하고 Category는 Many(has Many)에 속합니다. Post.
AR에 정의된 관계는 CActiveRecord의 관계() 메서드를 재정의해야 합니다. 이 메서드는 관계 구성의 배열을 반환합니다. 각 배열 요소는 다음 형식으로 단일 관계를 나타냅니다.
'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는 관계에 사용되는 외래 키를 지정합니다.
명확해야 할 몇 가지 사항:
(1) VarName은 무엇을 참조합니까? 자세한 내용은 아래 예제 2를 참조하세요.
(2),관계 유형. 총 4가지 유형이 있습니다. 즉,
self::HAS_MANY, self::BELONGS_TO, self::MANY_MANY, self::HAS_ONE입니다.
(3), 클래스 이름. 즉, 또 다른 연관된 ../model/classname.php입니다.
(4), ForeignKey. 외래 키는 누구에게 있습니까?
(5), 추가 조건
ER 다이어그램
예제 1, 일대다 및 다대일 관계(게시물과 사용자 간의 관계)
1) models/Post.php
class Post extends CActiveRecord { ...... public function relations() { return array( 'author'=>array(self::BELONGS_TO, 'User', 'author_id'), ); } }
게시물과 사용자 사이의 관계는 BELONGS_TO(다대일) 관계이며, 게시물의 작성자 ID를 통해 사용자와 연결됩니다.
Post의 Author_id는 외래 키이며 User와 연결되어 있습니다.
참고: 여기서 VarName은 작성자, 개체입니다.
(2) models/User.php
class User extends CActiveRecord { ...... public function relations() { return array( 'posts'=>array(self::HAS_MANY, 'Post', 'author_id'), 'profile'=>array(self::HAS_ONE, 'Profile', 'owner_id'), ); } }
User의 경우 Post와의 관계는 HAS_MANY(일대다) 관계입니다. 그리고 Post의 Author_id를 통해 Post와 연결됩니다.
예 2, 다대다 관계
in FailParts.php
'Users' => array(self::MANY_MANY, 'User', 'fail_parts_user(fail_parts_id, user_id)'),
in User.php
'FailParts' => array(self::MANY_MANY, 'FailParts', 'fail_parts_user(user_id, fail_parts_id)'),
둘은 다대다 관계이므로 , 따라서 사용자가 아닌 사용자를 사용하십시오. FailPart가 아닌 FailPart를 사용하십시오.
여기의 Users 및 FailParts는 이전 VarName입니다.
예시 3, 일대일 관계
비교적 간단하므로 일단 생략하겠습니다.
2, VarName 소개.
클래스 A.php의 경우 'VarName'=>array('RelationType', 'B', 'ForeignKey', ...추가 옵션)
여기서 VarName은 기본적으로 B와 동일합니다. 그러나 반드시 똑같지는 않습니다. 이때 A의 views/A/xx.php에 있는 VarName을 통해 B와 해당 속성값에 접근할 수 있습니다.
일대일인 경우: A->VarName
다대일인 경우:author_name = $post->Author->name;
일대다인 경우: $ Posts = $author->Post;
다대다인 경우: $posts = $author->Post;//핵심은 일대다와 다대일로 나누는 것입니다
foreach($posts as $u){ $_tmp_titles[] = $u -> title; } titleStr = implode(', ', $_tmp_titles);
2. 다중 테이블 연관의 사용
자주 컨트롤러에서
1, 지연 로딩
(1) 다대일
$post = Post::model()->findByPk(10); $author = $post->author;
참고: 여기서 핵심은 일대일입니다.
(2) 일대다
$user = User::model()->findByPk(10); $posts = $user->posts;
(3) 다대다
중요한 점은 두 ID 사이에 순차적 관계가 있다는 것입니다.
$repairInfo 인스턴스의 관점에서 연결은
'FailParts' => array(self::MANY_MANY, 'FailParts', 'repair_mapping(repair_info_id,fail_parts_id)'),
이어야 하며 $failParts 인스턴스의 관점에서 연결은
'RepairInfos' => array(self::MANY_MANY, 'RepairInfo', 'repair_mapping(fail_parts_id, repair_info_id)'),
이 됩니다. 필수는 아닙니다. 양면이 모두 구성되어 있으므로 필수 면만 설정하면 됩니다.
이전에 사용되었던 어리석은 방법:
/*方法一:使用表关系(多对多)*/ $fails = $repairInfo->FailParts;//在$repairInfo中使用 /*方法二:使用原始方法*/ $id = $repairInfo->id; $maps = RepairMapping::model()->findAll("repair_info_id = $id"); $f_ids = array(); foreach($maps as $map){ array_push($f_ids, $maps[0]->fail_parts_id); } $f_idsStr = implode(',',$f_ids); $fails = FailParts::model()->findAll("id IN ($f_idsStr)");
2, 활성 로딩 - with
(1) 일대다
(2) 다대다
$posts = Post::model()->('author')->findAll();
例子:
User.php
//查询一个机房$idc_id的所有用户 function getAdminedUsersByIdc($idc_id){ $c = new CDbCriteria(); $c->join = "JOIN idc_user on t.id=idc_user.user_id"; $c->condition = "idc_user.idc_id=$idc_id"; return User::model()->with('Idcs')->findAll($c); } //规则中配置 'Idcs' => array(self::MANY_MANY, 'Idc', 'idc_user(user_id, idc_id)'),
批注:没有with('Idcs'),执行后的结果也一样。只不过不再是eager loading。
三、带参数的关联配置
常见的条件有
1,condition 按某个表的某个字段加过滤条件
例如:
//在User的model里定义,如下关联关系 'doingOutsources' => array(self::MANY_MANY, 'Outsource', 'outsource_user(user_id, outsource_id)', 'condition' => "doingOutsources.status_id IN(" . Status::ASSIGNED . "," . Status::STARTED ."," . Status::REJECTED .")"),
//结论:condition是array里指定model的一个字段。
显然,doingOutsources是真实数据表Outsource的别名,所以在condition中可以使用doingOutsources.status_id,当然也可以使用Outsource.status_id。另本表名user的默认别名是t。
2,order 按某个表的某个字段升序或降序
//在RepairInfo的model里定义,如下关联关系 'WorkSheet' => array(self::HAS_MANY, 'WorkSheet', 'repair_info_id', order => 'created_at desc'), //调用 $worksheets = $repair_info->WorkSheet; //此时$worksheets是按降序排列
//结论:order是array里指定model的一个字段。
with
joinType
select
params
on
alias
together
group
having
index
还有用于lazy loading的
limit 只取5个或10个
offset
through
官方手册
'posts'=>array(self::HAS_MANY, 'post', 'author_id', 'order'=>'posts.create_time DESC', 'with'=>'categories'),
四、静态查询(仅用于HAS_MANY和MANY_MANY)
关键字:self:STAT
1,基本用法。例如,
class Post extends CActiveRecord { ...... public function relations() { return array( 'commentCount'=>array(self::STAT, 'Comment', 'post_id'), 'categoryCount'=>array(self::STAT,'Category','post_category(post_id, category_id)'); ); } }
2,静态查询也支持上面的各种条件查询
如
'doingOutsourceCount' => array(self::STAT, 'Outsource', 'outsource_user(user_id, outsource_id)', 'condition' => "outsource.status_id IN(" . Status::ASSIGNED . "," . Status::STARTED ."," . Status::REJECTED .")"),
其他查询还包括
condition 使用较多
order
select
defaultValue
params
group
having
3,静态查询的加载方式
可以使用lazy loading方式
$post->commentCount.
也可以使用eager loading方式
$posts = Post::model()->with('commentCount','categoryCount')->findAll();
注with中字符串一定是别名。
两者的性能比较:
如果需要取所有post的所有comment,前者需要2N+1次查询,而后者只有一次。两者的选择视情况而定。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
如何实现Yii2框架中使用PHPExcel导出Excel文件
위 내용은 YII 관련 검색어 분석에 대해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!