>  기사  >  백엔드 개발  >  YII 관련 쿼리에 대한 자세한 설명

YII 관련 쿼리에 대한 자세한 설명

*文
*文원래의
2017-12-28 15:29:041690검색

이 글은 주로 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은 관계의 이름입니다. 관계 유형은 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 대신 FailParts를 사용합니다.

여기의 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::model()->findByPk(10);
$author = $post ->author;

Comment: 여기서 핵심은 일대일입니다.

(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次查询,而后者只有一次。两者的选择视情况而定。

相关推荐:

Yii2中的代码自动加载机制

Yii框架中的form表单

Yii2实现增删改查后留在当前页的方法详解

위 내용은 YII 관련 쿼리에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.