2011-12-30 25 views
7

Yii Relational Tôi có một kỷ lục quan hệ tương tự như sau:kỷ lục với điều kiện từ bảng khác

  • Có người dùng (người sử dụng bảng) với id
  • Có nhiều loại (loại bảng) với id, tên
  • có bài viết (bài viết bảng) với id, cơ thể, category_id
  • Sau đó, có một read_articles bảng với article_id, user_id

Vì vậy, người dùng có thể xem danh sách tất cả các bài viết trong một danh mục. Họ có thể nhấp vào một bài báo và nó sẽ thêm một mục (user_id, article_id) vào bảng read_articles.

Tôi muốn có thể sử dụng ActiveRecord của Yii để nhận tất cả các bài viết từ một danh mục nhất định chưa được người dùng hiện tại đọc và hiển thị chúng. Tôi đã suy nghĩ về nó trong điều khoản của SQL một chút nhưng tôi không chắc chắn làm thế nào để phù hợp với nó vào thiết lập ActiveRecord của tôi. Ý tưởng đầu tiên của tôi là phạm vi tham số trên bản ghi Hoạt động của Bài viết:

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

Có vẻ như nó hoạt động nhưng cảm thấy thực sự dơ bẩn với tôi.

Có cách nào tốt hơn để làm những gì tôi đang nói trong ActiveRecord không? Hoặc tôi có nên xem xét việc chuyển sang SQL đơn giản hơn và xử lý những thứ như thế này (nhưng mất rất nhiều tính năng đẹp của AR)?

Sửa Dưới đây là các mối quan hệ cho các mô hình nêu trên: (Disclaimer, đây là những cắt ngắn để chỉ bộ phận liên quan)

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

Tôi cũng đã tạo một "UserReadArticleActiveRecord" ngay từ khi tôi đang xây dựng, nhưng tôi chưa bao giờ sử dụng mô hình đó và nó hoàn toàn trống rỗng.

Trong tất cả sự trung thực, tôi đã nghĩ đến việc chuyển sang Symfony2 và Doctrine dù sao đi nữa và chỉ bỏ toàn bộ bản ghi hoạt động. Tôi biết nó không giải quyết vấn đề này, nhưng tôi có thể chỉ cần thả này và giữ cho giải pháp hiện tại của tôi trong thời gian này.

+0

Bạn có quan hệ được định nghĩa từ các bài viết cho UserReadArticles không? Nếu vậy, tôi khá chắc chắn bạn có thể bao gồm tên quan hệ ở đâu đó trong phạm vi được đặt tên của bạn. – lucifurious

+0

Tôi có thể tạo UserReadArticles nhưng tôi không chắc chắn tôi biết làm thế nào để phù hợp với nó vào một phạm vi được đặt tên. – Matt

+0

chỉ cho tôi các mối quan hệ được xác định –

Trả lời

4

Để có được đọc bài viết, bạn có thể xác định một mối quan hệ MANY_MANY trên mô hình tài khoản của bạn như được mô tả ở đây:

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

Tôi không nghĩ rằng bạn sẽ cần UserReadArticles mô hình proxy, bạn chỉ cần xác định mối quan hệ đúng cách.

Để có được chưa đọc bài viết, tôi cũng đang gặp rắc rối suy nghĩ về cách Yii để làm điều đó, nhưng một cách hiệu quả hơn so với sử dụng một truy vấn phụ chọn là để làm một LEFT JOIN để user_read_articles và kiểm tra xem một cột từ user_read_articles IS NULL (không có hàng phù hợp) giống như sau:

$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', 
)); 
Các vấn đề liên quan