首頁 後端開發 php教程 YII關聯查詢詳解

YII關聯查詢詳解

Dec 28, 2017 pm 03:29 PM
關聯 查詢 詳解

本文主要介紹了YII關聯查詢的相關資料,需要的朋友可以參考下。希望對大家有幫助。

一、多表關聯的設定

在我們使用AR 執行關聯查詢之前,我們需要讓AR 知道一個AR 類別是怎樣關聯到另一個的。

兩個 AR 類別之間的關係直接透過 AR 類別所代表的資料表之間的關係相關聯。 從資料庫的角度來說,表A 和B 之間有三種關係:一對多(one-to-many,例如tbl_user 和tbl_post),一對一( one-to-one 例如tbl_user 和tbl_profile)和多對多(many-to-many 例如tbl_category 和tbl_post)。 在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 and self::MANY_MANY;ClassName 是此AR 類別所關聯的AR 類別的名字; ForeignKey 指定關係中使用的外鍵(一個或多個)。

需要弄清楚的幾點:

(1),VarName指什麼? 詳見下面例2。

(2),RelationType。共有4種,分別為

self::HAS_MANY, self::BELONGS_TO, self::MANY_MANY, self::HAS_ONE。

(3),ClassName。即關聯的另一個../model/類別名稱.php。

(4),ForeignKey。誰是誰的外鍵?

(5),附加條件

ER Diagram

#例1,一對多與多對一關係(post和user之間的關係)

1)models/Post.php


#
class Post extends CActiveRecord 
{ 
...... 
public function relations() 
{ 
return array( 
'author'=>array(self::BELONGS_TO, 'User', 'author_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'), 
'profile'=>array(self::HAS_ONE, 'Profile', 'owner_id'), 
); 
} 
}
登入後複製


對於User,與Post的關係是屬於HAS_MANY(一對多)關係。並透過Post的author_id與Post關聯。

範例2,多對多重關係

在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
如果是多對一:author_name = $post->Author->name;
如果一對多:$posts = $author->Post;
如果是多對多:$posts = $author->Post;//本質是拆成一對多和多對一


foreach($posts as $u){ 
$_tmp_titles[] = $u -> title; 
} 
titleStr = implode(', ', $_tmp_titles);
登入後複製



二、多表關聯的使用

常常在controllers裡

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

相关推荐:

Yii2中的代码自动加载机制

Yii框架中的form表单

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

以上是YII關聯查詢詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1325
25
PHP教程
1272
29
C# 教程
1252
24
12306怎麼查詢歷史購票紀錄 查看歷史購票紀錄的方法 12306怎麼查詢歷史購票紀錄 查看歷史購票紀錄的方法 Mar 28, 2024 pm 03:11 PM

12306訂票app下載最新版是一款大家非常滿意的出行購票軟體,想去哪裡就去那裡非常方便,軟體內提供的票源非常多,只需要通過實名認證就能在線購票,所有用戶的出行車票機票都可以輕鬆買到,享受不同的優惠折扣。還能提前開啟預約搶票,預約飯店、專車接送都是可以的,有了它想去哪裡就去那裡一鍵購票,出行更加簡單方便,讓大家的出行體驗更舒服,現在小編在線詳細為12306用戶帶來查看歷史購票記錄的方法。  1.打開鐵路12306,點擊右下角我的,點擊我的訂單  2.在訂單頁面點擊已支付。  3.在已支付頁

Win11管理員權限取得詳解 Win11管理員權限取得詳解 Mar 08, 2024 pm 03:06 PM

Windows作業系統是全球最受歡迎的作業系統之一,其新版本Win11備受矚目。在Win11系統中,管理員權限的取得是一個重要的操作,管理員權限可以讓使用者對系統進行更多的操作和設定。本文將詳細介紹在Win11系統中如何取得管理員權限,以及如何有效地管理權限。在Win11系統中,管理員權限分為本機管理員和網域管理員兩種。本機管理員是指具有對本機電腦的完全管理權限

學信網如何查詢自己的學歷 學信網如何查詢自己的學歷 Mar 28, 2024 pm 04:31 PM

學信網如何查詢自己的學歷?在學信網中是可以查詢到自己的學歷,很多用戶都不知道如何在學信網中查詢到自己的學歷,接下來就是小編為用戶帶來的學信網查詢自己學歷方法圖文教程,感興趣的用戶快來一起看看吧!學信網使用教程學信網如何查詢自己的學歷一、學信網入口:https://www.chsi.com.cn/二、網站查詢:第一步:點選上方學信網位址,進入首頁點選【學歷查詢】;第二步:在最新的網頁中點選如下圖箭頭所示的【查詢】;第三步:之後在新頁面點選【的登陸學信檔案】;第四步:在登陸頁面輸入資料點選【登陸】;

Oracle SQL中的除法運算詳解 Oracle SQL中的除法運算詳解 Mar 10, 2024 am 09:51 AM

OracleSQL中的除法運算詳解在OracleSQL中,除法運算是一種常見且重要的數學運算運算,用來計算兩個數相除的結果。除法在資料庫查詢中經常用到,因此了解OracleSQL中的除法運算及其用法是資料庫開發人員必備的技能之一。本文將詳細討論OracleSQL中除法運算的相關知識,並提供具體的程式碼範例供讀者參考。一、OracleSQL中的除法運算

MySQL與PL/SQL的異同比較 MySQL與PL/SQL的異同比較 Mar 16, 2024 am 11:15 AM

MySQL與PL/SQL是兩種不同的資料庫管理系統,分別代表了關係型資料庫和過程化語言的特性。本文將比較MySQL和PL/SQL的異同點,並附帶具體的程式碼範例進行說明。 MySQL是一種流行的關聯式資料庫管理系統,採用結構化查詢語言(SQL)來管理和操作資料庫。而PL/SQL是Oracle資料庫特有的過程化語言,用於編寫預存程序、觸發器和函數等資料庫物件。相同

PHP模運算子的作用及用法詳解 PHP模運算子的作用及用法詳解 Mar 19, 2024 pm 04:33 PM

PHP中的模運算子(%)是用來取得兩個數值相除的餘數的。在本文中,我們將詳細討論模運算子的作用及用法,並提供具體的程式碼範例來幫助讀者更好地理解。 1.模運算子的作用在數學中,當我們將一個整數除以另一個整數時,就會得到一個商和一個餘數。例如,當我們將10除以3時,商數為3,餘數為1。模運算子就是用來取得這個餘數的。 2.模運算子的用法在PHP中,使用%符號來表示模

蘋果手機怎麼查詢啟動日期 蘋果手機怎麼查詢啟動日期 Mar 08, 2024 pm 04:07 PM

使用蘋果手機想要查詢啟動日期,最好的方法是透過手機中的序號來查詢,也可以透過存取蘋果的官網來進行查詢,透過連接電腦查詢,下載第三方軟體查詢。蘋果手機怎麼查詢啟動日期答:序號查詢,蘋果官網查詢,電腦查詢,第三方軟體查詢1、用戶最好的方式就是知道自己手機的序號,開啟設定通用關於本機就可以看到序號。 2.使用序號不僅可以知道自己手機的啟動日期,還可以查看手機版本,手機產地,手機出廠日期等。 3.用戶訪問蘋果的官網找到技術支持,找到頁面底部的服務和維修欄目,裡面查看iPhone的激活信息。 4.用戶

Discuz資料庫位置查詢技巧分享 Discuz資料庫位置查詢技巧分享 Mar 10, 2024 pm 01:36 PM

論壇是網路上非常常見的網站形式之一,它為使用者提供了一個分享資訊、交流討論的平台。而Discuz是一款常用的論壇程序,相信很多站長都已經非常熟悉了。在進行Discuz論壇的開發和管理過程中,經常需要查詢資料庫中的資料來進行分析或處理。在這篇文章中,我們將分享一些查詢Discuz資料庫位置的技巧,並提供具體的程式碼範例。首先,我們需要了解Discuz的資料庫結構

See all articles