我們已經了解了怎樣使用 Active Record (AR) 從單個數據表中獲取數據。 在本節中,我們講解怎樣使用 AR 連接多個相關 數據表並取回關聯(join)後的數據集。
為了使用關系型 AR,我們建議在需要關聯的表中定義主鍵-外鍵約束。這些約 束可以幫助保證相關數據的一致性和完整性。
本例通過修改Yii Framework 開發教程(25) 數據庫-Query Builder示例來 介紹多個有關系的表如何使用Active Record。
在我們使用 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() 方法。此方法返回一個關系配置數組。每個數組元素通過如下格式表示一個單一的關系。
在Query Builder中我們使用了下面SQL查詢語句
SELECT c.FirstName, c.LastName , c.Address,c.Email FROM customer c INNER JOIN employee e ON c.SupportRepId=e.EmployeeId WHERE e.EmployeeId=4
涉及到兩個表格Employee 和 Customer,Employee和Customer之間是一對多的關系,也就是說 一個員工可以負責多個客戶。Employee到Customer的關系為HAS_MANY, Customer到Employee的關系為HAS_ONE。因此可以定義 Employee和Customer如下:
//Customer.php class Customer extends CActiveRecord { public static function model($className=__CLASS__) { return parent::model($className); } public function tableName() { return 'Customer'; } } //Employee.php class Employee extends CActiveRecord { public static function model($className=__CLASS__) { return parent::model($className); } public function tableName() { return 'Employee'; } public function relations() { return array( 'customers'=>array(self::HAS_MANY, 'Customer', 'SupportRepId'), ); } }
因為本例只使用到由Employee查詢對應的Customer,因此只為類定義了relations方法。對應的表和外鍵為Customer 和SupportRepId。
然後修改SiteController的indexAction方法:
public function actionIndex() { $employee=Employee::model()->findByPk(4); $this->render('index', array( 'model' => $employee->customers, )); }