Yii框架中ActiveRecord使用 Relations

  • 前提條件  

在組織數據庫時,需要使用主鍵與外鍵約束才能使用ActiveReocrd的關係操作;

  • 場景

下面的一個ER圖顯示的是一個例子

ER圖
 

申明關係

兩張表之間的關係無非三種:一對多;一對一;多對多; 在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)

 

VarName 關係名
RelationType 四種關係:self::BELONGS_TO, self::HAS_ONE, self::HAS_MANY,self::MANY_MANY
ClassName 代表當前AR類要關聯的那個AR類名
ForeignKey 實現關係的外鍵, 有可能有多個,即列名

下面的代碼表示用來定義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
定義別名,當多個表中有相同的columnname時,需要爲表格定義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 User extends CActiveRecord
{
public function relations()
{
return array(
'posts'=>array(self::HAS_MANY, 'Post', 'author_id',
'order'=>'posts.create_time DESC',
'with'=>'categories'),
'profile'=>array(self::HAS_ONE, 'Profile', 'owner_id'),
);
}
}

此時,我們使用$author->posts時,會返回固定ORDER的POST信息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章