我有一个类似于以下内容的关系记录:
因此,用户可以查看某个类别中所有文章的列表。他们可以点击文章,它会在read_articles表中添加一个条目(user_id,article_id)。
我希望能够使用Yii的ActiveRecord来获取当前用户尚未读取的给定类别的所有文章并显示这些文章。我在SQL方面一直在考虑它,但我不确定如何将它放入我的ActiveRecord设置中。我的第一个想法是文章活动记录的参数化范围:
public function unread( $userId )
{
$this->getDbCriteria()->mergeWith( array(
'alias' => 'articles',
'condition' => 'not exists (SELECT * '
. 'FROM user_read_articles '
. 'WHERE articles.id=user_read_articles.article_id '
. 'AND read_articles.user_id=' . (int)$userId
. ')',
) );
}
它似乎有效,但对我来说感觉很脏。
有没有更清晰的方法来处理我在ActiveRecord中所说的内容?或者我应该考虑转向更简单的SQL并自己处理这样的事情(但是失去了很多很好的AR功能)?
编辑以下是上述模型的关系:(免责声明,这些仅被截断为相关部分)
UserActiveRecord
public function relations()
{
return array(
'categories' => array(
self::HAS_MANY,
'UserCategoryActiveRecord',
'user_id' ),
// I added this early using gii, never really used it...
'readArticles' => array(
self::HAS_MANY,
'UserReadArticleActiveRecord',
'user_id' ),
);
}
UserCategoryActiveRecord
public function relations()
{
return array(
'user' => array(
self::BELONGS_TO,
'UserActiveRecord',
'user_id' ),
'articles' => array(
self::HAS_MANY,
'ArticleActiveRecord',
'category_id',
'order' => 'articles.pub_date DESC' ),
);
}
ArticleActiveRecord
public function relations()
{
return array(
'category' => array(
self::BELONGS_TO,
'CategoryActiveRecord',
'category_id' ),
);
}
我在构建它的过程中也提出了一个“UserReadArticleActiveRecord”,但我从未使用过该模型,它几乎只是空的。
老实说,我一直在考虑转向Symfony2和Doctrine,只是放弃了积极的记录。我知道它并没有解决这个问题,但我可能会放弃这个并暂时保留我目前的解决方案。
答案 0 :(得分:4)
要获取阅读文章,您可以在用户模型上定义MANY_MANY关系,如下所述:
http://www.yiiframework.com/doc/guide/1.1/en/database.arr
我认为您不需要代理模型UserReadArticles,您只需要正确定义关系。
要获取未读文章,我也无法考虑使用Yii的方法,但使用子选择查询的一种更有效的方法是对user_read_articles进行LEFT JOIN并检查user_read_articles中的列是否为NULL(没有匹配的行),如下所示:
$this->getDbCriteria()->mergeWith( array(
'alias' => 'articles',
'join' => 'LEFT JOIN user_read_articles ON articles.id=user_read_articles.article_id',
'condition' => 'user_read_articles.article_id IS NULL',
) );