2012-08-06 74 views
4

,用於存儲關於某些網站用戶定義的書籤,我與複合鍵的表:關係的Yii ActiveRecord的用於表複合具有NULL鍵值

CREATE TABLE bookmarks (
    user_id int not null, 
    book_id int not null, 
    page_id int, 
    ... 
); 
CREATE UNIQUE INDEX ON bookmarks(user_id, book_id, page_id); 

。注意,PAGE_ID可以爲NULL,和USER_ID而book_id不能。當page_id爲空時,爲整本書設置書籤,否則 - 對於某個頁面。

相應的ActiveRecord類定義了一些關係:

public function relations() { 
    return array(
     "user" => array(self::BELONGS_TO, "User",  "user_id"), 
     "book" => array(self::BELONGS_TO, "Book",  "book_id"), 
     "page" => array(self::BELONGS_TO, "Page",  "page_id"), 
    ); 
} 

和的PrimaryKey()方法::

public function primaryKey() { 
    return array("user_id", "book_id", "orig_id"); 
} 

現在我想所有書籤了整本書的一些用戶。所以,我做的:

$bookmarks = Bookmark::model()->findAll(array(
    "condition" => "t.user_id = :user_id AND t.page_id IS NULL", 
    "params" => array(":user_id" => 1), 
)); 

它的偉大工程,返回4條記錄,但很明顯,我想從書本上表中使用的一些相關數據:

$bookmarks = Bookmark::model()->findAll(array(
    "with" => "book", 
    "condition" => "t.user_id = :user_id AND t.page_id IS NULL", 
    "params" => array(":user_id" => 1), 
)); 

,現在我得到0的記錄(COUNT( $書籤)== 0),儘管生成的SQL語句選擇了所有需要的數據,但它僅僅被CActiveRecord類所識別。另一個奇怪的是,當我嘗試獲取所有頁面書籤時,一切正常:

$bookmarks = Bookmark::model()->findAll(array(
    "with" => "book", 
    "condition" => "t.user_id = :user_id AND t.page_id IS NOT NULL", 
    "params" => array(":user_id" => 1), 
)); 

我在做什麼錯了?如何在第二個例子中表達返回一些數據? PHP 5.4.0,Yii 1.1.8,PostgreSQL 9.1.4,+ 32 ° C以外。

+0

很久以前,我一直在使用YII,據我記得你應該使用書籤:: model() - >('book');' – Leri 2012-08-06 12:04:45

+0

@PLB,我認爲* Conditions *將被合併,所以不會有太大的區別(但是在這裏+ 35°C,所以我可能是非常錯誤的)。 uisky,* book_id *這行沒有NULL值,對吧? – 2012-08-06 12:27:56

+0

@Boris Belenski,正確,user_id和book_id沒有NULL的 – uisky 2012-08-06 12:40:46

回答

3

您的問題可以通過這種方式來解決:

  1. 添加的替代PK書籤表(例如自動遞增序列)。

  2. 刪除primaryKey()功能。

您也可以使用更方便代碼:控制器只是

public function relations() 
{ 
    return array(
     //... 
     'wholeBook' => array(self::BELONGS_TO, 'Book', 'book_id', 'on'=>"page_id IS NULL", 'joinType'=>'INNER JOIN'), 
     //... 
    ); 
} 

然後:

$bookmarks = Bookmark::model()->with('wholeBook')->findAllByAttributes(array('user_id'=>1)); 

由於事實上,具有獨特的密鑰,而不是主要和primaryKey()你使用hack來避免在複合PK中使用NULL列的不可能性。 ActiveRecord是一種ORM,所以SQL中的任何邏輯都必須翻譯成AR(Yii會自動加載DB模式),並且它必須是正確的邏輯。

如果我是你,我會正常化的SQL是這樣的: Normalized DB structure

因爲那些是兩種不同類型的不同關係的書籤。你應該只在視圖邏輯中加入它們,而不是在關係結構中。恕我直言