簡體   English   中英

CakePHP:使用多級可包含行為

[英]CakePHP: Using multilevel Containable Behaviour

我已經花了一些時間嘗試在CakePHP中使用Containable Behavior,但我無法讓它像我預期的那樣工作。

我的應用程序是不同的,但為了簡化,我將把這個例子。 假設我有一個包含線程和活動的論壇,可以對活動進行評級。 一般關系是:

論壇:hasMany [主題]
線程:belongsTo [論壇],hasMany [活動]
活動:belongsTo [Thread],hasMany [Rating]
評分:belongsTo [活動]

我想要實現的是,使用find方法,獲得在某個論壇上執行的所有評級。 我認為應該做的是以下內容:

 $this->Rating->find('count', array(
    'contain' => array(
        'Activity' => array(
            'Thread'
        )
    ),
    'conditions' => array(
        'Thread.forum_id' => 1
    )
));

但結果查詢是:

SELECT COUNT(*) AS `count` FROM `ratings` AS `Rating` LEFT JOIN `activities` AS `Activity` ON (`Rating`.`activity_id` = `Activity`.`id`) WHERE `Thread`.`forum_id` = 1;

我使用'join'選項完成了這個,但它更復雜,我必須在很多情況下使用這種動作。

可以在此處找到與該示例相關的所有文件: http//dl.dropbox.com/u/3285746/StackOverflow-ContainableBehavior.rar

謝謝

更新23/11/2011

在調查框架后,感謝Moz Morris和api55的答案,我找到了問題的根源。

基本的問題是,正如我所理解的CakePHP,我以為它每次都在使用連接進行查詢。 它不會這樣做的事情,它將獲得我正在尋找的結果的實際操作將是這樣的:

SELECT * FROM Rating JOIN Activity...
SELECT * FROM Activity JOIN Thread...
SELECT * FROM Activity JOIN Thread...
...

這意味着它將執行查詢以獲取所有活動,然后,對於每個活動,執行查詢以獲取線程...我的方法失敗不是因為使用了可包含行為錯誤,而是因為'條件'選項已應用於所有查詢,並且在第一個查詢中,由於缺少Thread表而崩潰。 找到這個后,有兩種可能的解決方案:

  • 正如api55所說,使用'contains'數組中的條件,它只會將它們應用於使用Thread表的查詢。 但是這樣做仍然存在問題,因為我們有太多的查詢。

  • 正如Moz Morris所說,將Thread模型綁定到Rating也會起作用,它會執行單個查詢,這就是我們想要的。 問題在於,我認為這是一個跳過模型之間的關系而不遵循CakePHP哲學的補丁。

我將api55解決方案標記為正確,因為它解決了我遇到的具體問題,但兩者都解決了問題。

首先,您是否將actAs包含在appModel中? 沒有它這個beahaviour根本不會工作(我發現它沒有正常工作,因為它沒有與Thread表連接)

我會從頂部做到這一點,我的意思是從論壇,所以你選擇你的論壇(我不確定你想要論壇或線程)並得到它的所有評級,如果沒有評級你將最終評級鍵為空。

這樣的事情

appModel

public $actsAs = array('Containable');

評級控制器

 $this->Rating->Activity->Thread->Forum->find('count', array(
    'contain' => array(
        'Thread' => array(
             'Activity' => array(
                 'Rating' => array (
                       'fields' => array ( 'Rating.*' )
                  )
              )
        )
    ),
    'conditions' => array(
        'Forum.id' => 1
    )
));

然后,如果您只需要一個評級表中的值,只需使用Set:extract來獲取此值的數組。

正如你所做的那樣,IT應該繼續工作,但我不會在那里使用forum_id,但在內部條件包含這樣的

'contain' => array(
    'Activity' => array(
        'Thread' => array(
              'conditions' => array('Thread.forum_id' => 1)
         )
    )
),

此外,永遠不要忘記使用可包容的行為(或在應用程序模型中)中的actsAs變量

惠斯特我喜歡api55的解決方案,我認為結果有點亂 - 取決於你打算用數據做什么我猜。

我假設當你說使用'join'方法時你正在討論使用這種方法:

$this->Rating->bindModel(array(
  'belongsTo' => array(
    'Thread' => array(
      'foreignKey' => false,
      'conditions' => 'Thread.id = Activity.thread_id',
    ),
    'Forum' => array(
      'foreignKey' => false,
      'conditions' => 'Forum.id = Thread.forum_id'
    )
  )
));

$ratings = $this->Rating->find('all', array(
  'conditions' => array(
    'Forum.id' => 1 // insert forum id here
  )
));

這對我來說似乎有點干凈,而且您不必擔心在AppModel中使用可包含的行為。 值得考慮。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM