在 CActiveRecord::relations() 中聲明 self::STAT 類型關聯,用於獲取關聯對象的**聚合信息**(計數、求和、平均值等),而非具體記錄。
適用關係:HAS_MANY、MANY_MANY。
class Post extends CActiveRecord {
public function relations() {
return [
// 評論數:Post HAS_MANY Comment (post_id)
'commentCount' => [self::STAT, 'Comment', 'post_id'],
// 分類數:Post MANY_MANY Category 通過中間表 post_category
'categoryCount' => [self::STAT, 'Category', 'post_category(post_id, category_id)'],
// 進階:指定聚合表達式(Yii 1.1.14+)
'totalViews' => [self::STAT, 'PostView', 'post_id', 'select' => 'SUM(views)'],
'avgRating' => [self::STAT, 'Rating', 'post_id', 'select' => 'AVG(score)'],
];
}
}
$post = Post::model()->findByPk(1);
echo $post->commentCount; // 自動執行 SELECT COUNT(*) FROM comment WHERE post_id=1
echo $post->categoryCount; // 自動執行關聯表 COUNT 查詢
$posts = Post::model()->with('commentCount', 'categoryCount')->findAll();
foreach ($posts as $post) {
echo $post->title . ': ' . $post->commentCount . ' 條評論';
}
// 僅執行 3 條 SQL:主查詢 + 兩條統計子查詢(JOIN 或子查詢)
$posts = Post::model()->published()->recently()->with('comments')->findAll();
$posts = Post::model()->with('comments:recently:approved')->findAll();
// comments 關聯應用 recently 和 approved 兩個命名範圍
class User extends CActiveRecord {
public function relations() {
return [
'posts' => [self::HAS_MANY, 'Post', 'author_id', 'with' => 'comments:approved'],
];
}
}
// $user->posts 直接包含已審核評論
'commentCount' => [
self::STAT, 'Comment', 'post_id',
'select' => 'COUNT(DISTINCT user_id)' // 統計不同用戶評論數
],
'approvedCommentCount' => [
self::STAT, 'Comment', 'post_id',
'condition' => 'status=1' // 僅統計通過審核的評論
],
若關聯模型定義了 defaultScope(),統計查詢**會自動應用**該範圍。如需忽略,可在統計關聯中設置 'defaultScope' => false(Yii 1.1.13+)。
with() 急切加載**,避免 N+1 問題。comment_count 欄位,寫入時同步更新(觸發器/應用層),讀取時零查詢開銷。SELECT COUNT(*) ...,確保關聯外鍵欄位有**索引**。$post->commentCount 只查詢一次;跨請求需自行緩存(Redis/Memcached)。$post->commentCount 會覆蓋字段值。