2011-12-30 15 views
7

que tiene un registro de relación similar a la siguiente:registro Yii relacional con la condición de otra tabla

  • Hay usuarios (usuarios de mesa) con los identificadores de
  • Hay categorías (categorías de mesa) con el ID, nombre
  • hay artículos (artículos de mesa) con el ID, cuerpo, category_id
  • entonces hay una mesa con read_articles article_id, uSER_ID

Para que un usuario pueda ver una lista de todos los artículos en una categoría. Pueden hacer clic en un artículo y agregarán una entrada (user_id, article_id) a la tabla read_articles.

Quiero ser capaz de utilizar el ActiveRecord de Yii para obtener todos los artículos de una categoría determinada que no hayan sido leídos por el usuario actual y mostrarlos. He estado pensando en ello en términos de SQL un poco, pero no estoy seguro de cómo encajarlo en mi configuración de ActiveRecord. Mi primera idea fue un ámbito parametrizado en el registro activo Artículo:

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 
      . ')', 
    )); 
} 

Parece estar funcionando, pero se siente muy sucia para mí.

¿Hay alguna manera más clara de hacer lo que estoy diciendo en ActiveRecord? ¿O debería considerar cambiar hacia un SQL más simple y manejar cosas como esta yo mismo (pero perder una gran parte de la buena característica de AR)?

Editar Aquí son las relaciones de los modelos anteriormente mencionados: (Negación, estos son trunca a sólo partes relevantes)

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'), 
    ); 
} 

También hice un "UserReadArticleActiveRecord" desde el principio mientras construía esto, pero nunca usé ese modelo y está casi vacío.

Honestamente, he estado pensando en mudarme a Symfony2 y Doctrine de todos modos y acabando con el registro activo por completo. Sé que no resuelve este problema, pero podría dejar esto y conservar mi solución actual por el momento.

+0

¿Tiene una relación definida de los artículos a UserReadArticles? Si es así, estoy bastante seguro de que puede incluir el nombre de la relación en algún lugar de su alcance designado. – lucifurious

+0

Podría hacer UserReadArticles pero no estoy seguro de cómo encajarlo en un ámbito determinado. – Matt

+0

muéstrame las relaciones definidas –

Respuesta

4

Para obtener el leer artículos, se puede definir una relación MANY_MANY del modelo de usuario como se describe aquí:

http://www.yiiframework.com/doc/guide/1.1/en/database.arr

No creo que necesita los UserReadArticles modelo proxy, solo necesita definir la relación correctamente.

Para obtener sin leer artículos, también estoy teniendo problemas para pensar acerca de la manera Yii a hacerlo, pero de una manera más eficaz que utilizar una consulta sub-select es hacer un JOIN LEFT a user_read_articles y verificar si hay una la columna de user_read_articles IS NULL (no había fila coincidente) algo como esto:

$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', 
)); 
Cuestiones relacionadas