Реляционная запись Yii с условием из другой таблицы
у меня есть реляционная запись, подобная следующей:
- есть пользователи (пользователи таблицы) с идентификаторами
- есть категории (категории таблицы) с id, name
- есть статьи (статьи таблицы) с идентификатором, телом, category_id
- тогда есть таблица read_articles с article_id, user_id
таким образом, пользователь может видеть список всех статей в категории. Они могут нажать на статью, и она добавит запись (user_id, article_id) в таблицу read_articles.
Я хочу иметь возможность использовать ActiveRecord Yii, чтобы получить все статьи из данной категории, которые не были прочитаны текущим пользователем, и отобразить их. Я немного думал об этом с точки зрения SQL, но я не уверен, как вписать его в мою настройку ActiveRecord. Моей первой идеей была параметризованная область действия статьи active record:
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)?
редактировать вот отношения для вышеупомянутых моделей: (отказ от ответственности, они усечены только до соответствующих parts)
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 в любом случае и просто бросить активную запись вообще. Я знаю, что это не решит эту проблему, но я мог бы просто отбросьте это и сохраните мое текущее решение на некоторое время.
1 ответов
для получения читать статьи, вы можете определить many_many отношения на вашей модели пользователя, как описано здесь:
http://www.yiiframework.com/doc/guide/1.1/en/database.arr
Я не думаю, что вам понадобится прокси-модель UserReadArticles, вам просто нужно правильно определить отношения.
и прочитано статьи, у меня также возникают проблемы с тем, как это сделать, но более эффективный способ, чем использование запроса sub-select - это сделать левое соединение с user_read_articles и проверить, является ли столбец из user_read_articles нулевым (не было совпадающей строки) что-то вроде этого:
$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',
) );