文章目錄
Yii架構中ActiveRecord使用Relations
在組織資料庫時,需要使用主鍵與外鍵約束才能使用ActiveReocrd的關係操作;
申明關係
兩張表之間的關係無非三種:一對多;一對一;多對多; 在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 |
這個對應多對多的情況,在AR裡會將多對多以BELONGS_TO和HAS_MANY的組合來解釋 |
Post和Category |
在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 |
實現關係的外鍵, 有可能有多個,即列名 |
下面的代碼錶示用來定義Post, User之間的關係
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)'), ); }} 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'), ); }}使用時,如果$author代表一個USER的AR執行個體,可以使用$author->posts來擷取到它相關的所有的Post對象。
執行關係查詢懶惰匯入查詢方法最簡單的方法就是為AR對象添加一個關聯屬性,
例:
// 擷取PK為10的POST對象 $post=Post::model()->findByPk(10); // 擷取這個POST的作者 $author=$post->author;
如果沒有關聯的對象,那麼將返回NULL或者一個空數組;BELONGS_TO和HAS_ONE結果為NULL,而HAS_MANY和MANY_MANY返回一個空數組。
上面的這種“懶惰匯入”方法使用起來非常方便,但是在一些情境下不是非常的效率,比如,如果我們想訪問N個POST的作者的資訊,使用這種懶惰匯入的方法將會執行N個join查詢;
急切匯入查詢方法下面介紹是一種“急切匯入”方法:在使用find和findAll時,使用with()方法,例:
$posts=Post::model()->with('author')->findAll()這樣就可以在一次查詢時連同查詢其他資訊了;with方法可以接受多個關係:
$posts=Post::model()->with('author','categories')->findAll();這樣就可以將作者和類別的資訊一併進行查詢;同樣,with還支援多重急切匯入
$posts=Post::model()->with( 'author.profile', 'author.posts', 'categories')->findAll();
上面的代碼不僅會返回autho和categories資訊,還會返回作者的profile和posts資訊這種“急切匯入”方法也支援CDbCriteria::with,下面這兩種實現方式效果一樣:
$criteria=new CDbCriteria; $criteria->with=array( 'author.profile', 'author.posts', 'categories', ); $posts=Post::model()->findAll($criteria); or $posts=Post::model()->findAll(array( 'with'=>array( 'author.profile', 'author.posts', 'categories', ) );
關係查詢選項前面提過,在申明關係時可以添加額外的選項,這些選項都是一些key-value對,是用來定製關係查詢的,總結如下:
-
select
-
定義從AR類中被select的列集合,如果定義為*,則表示查詢所有列
-
condition
-
定義where語句,預設為空白。
-
params
-
產生SQL語句的參數,這個需要用一個key-value對的數組來表示;
-
on
-
ON語句,這個條件用來通過AND添加一個joining condintion語句
-
order
-
ORDER語句
-
with
-
和當前對象一起匯出的相關對象列表,要注意如果使用不正確,有可能導致無限死迴圈;
-
joinType
-
定義join的類別,預設為LEFT OUTER JOIN
-
alias
-
定義別名,當多個表中有相同的column name時,需要為表格定義alias,然後使用tablename.columnname來指定不同的column
-
together
-
這個只在HAS_MANY, MANY_MANY時有用,在實現跨表查詢時,可以用這個參數來控制效能。正常用不到,不詳細講述;
-
join
-
JOIN語句
-
group
-
GROUP語句
-
having
-
HAVING語句
-
index
-
這個值用來設定返回的結果數組以哪個column做為index值,如果不設定這個值的話,將從0開始組織結果數組。
除此之外還包含下面幾個選項,在“懶惰匯出”的特定關係時可用
-
limit
-
返回結果數量的限制,不適用於BELONG_TO關係
-
offset
-
offset結果數量的值,不適用於BELONG_TO關係
下面代碼,顯示上面選項的一些使用:
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)'), ); }} 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'), ); }}此時,我們使用$author->posts時,會返回固定ORDER的POST資訊