2013-02-21 141 views
2

我有一個相同類的活動記錄對象的數組。 該對象具有已定義的關係。 在「父」對象初始化之後,有沒有辦法以「批量」方式讀取相關對象?初始化父對象後初始化相關的對象

例 我已經定義AR類郵政用戶註釋 * 郵政 *有關係所有者(belongs_to的)到類用戶和關係評論(HAS_MANY)到類評論

我有一個數組的對象的$帖子。 對於不同的原因,$帖子不能從一開始初始化

'with' => array('owner', 'comments') 

如果我這樣做:

foreach ($posts as $post) { 
    var_dump($post->owner); 
    var_dump($post->comments); 
} 

$發佈查詢對子級的retriving 所有人提出和查詢評論。 這可能會導致大量查詢和腳本執行緩慢。 更好的方法是在一個步驟中讀取一種類型的所有相關對象。

難道這樣的事情存在retriving有一定關係的所有相關對象爲對象的數組?:

Post::readRelatedObject($posts, 'owner'); 
Post::readRelatedObject($posts, 'comments'); 

我需要這個形式給出的幾個原因:

  1. 有時我不能提前告訴我是否需要關係初始化。
  2. 在「父母」之後閱讀相關對象可能會快得多,因爲連接速度可能會很慢。
  3. 緩存可能會受到影響,因爲有時候「父」對象不能與相關對象具有相同的緩存時間,因此,在從緩存中提取父對象後,以分組/批量方式讀取相關對象可能是有用的。例如:$ post已被緩存,但我無法緩存最後3條評論和帖子。

yii是否包含這樣的東西?或者可以幫助的插件?

謝謝

+0

這是什麼原因,當初始化'$ posts'數組時,你不能指定'with'? – dInGd0nG 2013-02-22 05:42:37

+0

@ dInGd0nG我有三個主要原因: 1.性能。我有很多關係的對象。如果我使用「with」加入它們,則可能會導致查詢速度很慢且很慢。 2.遺留代碼。作爲一個函數的結果,我有對象的父對象(在示例$ posts中)。將相關對象附加到結果上會更方便,而不是修改該函數(這可能導致破壞代碼的其他部分)。 3.靈活性。我不會被迫事先考慮我需要什麼樣的關係,我可以輕鬆地(並且減少數據庫壓力)將關係附加到一組父對象上。 – humeniuc 2013-02-22 07:15:55

回答

0

我不知道可以做到這一點的擴展。也許你可以創建一個yii應該知道關於數據的一切來解決這個任務。

比方說comment有一個post_id,它鏈接到post表中的id

有幾個選項可以加載帖子的相關評論。

選項1:使用ID來查詢所需的註釋。某些DBMS限制了SQL查詢的長度,因此您可能必須小心並且不要在IN子句中放置許多ID。也許這必須分解成多個查詢。

  1. 迭代給定$posts和存儲後id S IN的列表。運行SQL查詢SELECT * FROM comments WHERE post_id IN ([the IDs from the list])
  2. 將結果合併到您的$posts中。

選項2:要修復可能的IN子句限制,請改用JOIN。

  1. 運行一個SQL查詢,如SELECT * FROM comments JOIN [the SELECT query for the posts]

選項3(我的首選):根據您的使用情況下,它可能是最乾淨的,只是重裝意見和作者的所有帖子(在posts模型上criteria定義with)。

  1. 添加條件withif ($loadDetails) { criteria->'with' => array('owner', 'comments'); }
0

如果你的主要問題是避免延遲加載,想檢索所有郵政與業主和評論的相關記錄。

這可能對你有用。

$criteria = new CDbCriteria(); 
$criteria->with = array('comments','owner'); 
$result = $Post->together()->findAll($criteria); 

參考: http://www.yiiframework.com/doc/api/1.1/CActiveRecord#together-detail http://www.yiiframework.com/doc/api/1.1/CDbCriteria#with-detail

希望這回答了你的查詢。

+0

該程序是我需要的反例。我不能和一起使用。在簡單的帖子和評論的例子中,如果我需要顯示100個帖子,並且每個人都有200個評論,那麼with +會一起創建一個生成2000行的查詢。在實際應用中,這個過程可能會導致非常緩慢的查詢 – humeniuc 2013-02-28 04:24:55

+0

我有點困惑。 – 2013-02-28 07:48:49

2

如果你想爲這樣的大型結果集進行優化,那麼你幾乎總是可以更好地使用自己的。 Yii的開發者even recommend對於像這樣的複雜情況沒有使用activerecord(加載順序非常不同)。

雖然

首先,我建議建立一個基於你找回所有帖子的ID自己CDBCriteria。如果你在Posts模型中這樣做,它也很好地(顯然不完美)與爲關係定義的標準相關聯。

static public function loadComments(array $ids) 
{ 
    $crit = Comment::model()->dbCriteria; 
    $crit->addInCondition('post_id', ..... 

    ..... 
    return Comment::model()->findAll($crit); 
} 

這將使你的所有意見回該集ID,你甚至可以通過他們所屬太帖子ID做一些額外的處理,生成索引文件。

但是,真的

在你的評論說,這100個職位200個評論的每可能意味着裝載2000(實際是20 000)。但是,如果您在單個頁面上加載了許多帖子+評論,則會在錯誤的位置進行優化。

你有幾件事情在我看來擔心DB查詢大小之前實現:

  1. 不要加載評論正在直至需要它們,這是在點擊一個按鈕,滾動到該帖子'標題或簡單地逐漸下到頁面,直到完成。這樣,服務器一次只查找一篇文章的評論,而用戶甚至不希望看到帖子編號爲99的評論。

  2. 不要每頁加載100篇文章,除非它們非常小帖子(在這種情況下,有什麼擔心)。再次進行滾動會有所幫助,或者甚至可以幫助您進行滾動,或者甚至可以幫助您進行滾動,或者甚至可以幫助您進行滾動,或者甚至可以不用100個用戶希望看到的帖子,如果有200條評論,有多少用戶會閱讀10條以上?

如果你甚至實現了其中一個,我認爲結果集大小的問題將會消失。

然而

如果你真的需要擔心20 000行,ActiveRecord的實例應該是您第一個雷達。在任何正常的設置中,20 000行是無需擔心的,但即使在更高規格的系統上,也有20 000行活動記錄對象。如果你正在處理非常大的和/或複雜的數據集,你應該使用DAO。

+0

與帖子,評論,用戶的情況純粹是示範。返回的結果數量相同,因此不是頁面結構,加載程序等是問題。 Hoever感謝您對不使用ActiveRecord的消解。看起來AR是爲了簡單的任務而設計的。 Yii在他們的AR中沒有'post對象初始化批量初始化關係'功能是一個恥辱。 – humeniuc 2013-03-02 19:43:13

+0

這真是一個恥辱,但如果你寫了一個,分享它,它可能會進入Yii 2.0:p – Paystey 2013-03-02 22:39:31