2008-09-22 80 views
0

我有一個n...n結構兩個表,makesmodels。到目前爲止沒有問題。如何在CakePHP中的第三個n..n(hasAndBelongsToMany)關係中連接兩個表?

在第三個表(products),如:

id 
make_id 
model_id 
... 

我的問題是創建包含一個specifi make產品我ProductsController內部的觀點只是我們做的模型:

我認爲這可以工作:

var $uses = array('Make', 'Model'); 

$this->Make->id = 5; // My Make 

$this->Make->find(); // Returns only the make I want with it's Models (HABTM) 
$this->Model->find('list'); // Returns ALL models 
$this->Make->Model->find('list'); // Returns ALL models 

所以,如果我想使用list傳遞給我的視圖中創建單選按鈕我會做一個foreach()make陣列找到所有車型的標題,並創建一個新的數組,並通過$this->set()發送到視圖。

$makeArray = $this->Make->find(); 
foreach ($makeArray['Model'] as $model) { 
    $modelList[] = $model['title']; 
} 
$this->set('models', $models) 

有沒有更簡單的方法來獲取列表而不強調make陣列。在我的應用程序中開發這樣的場景將是一個普遍的任務。

在此先感謝您的任何提示!

回答

1

這裏是我的提示:在嘗試使用Cake庫重新構建之前,嘗試使用常規SQL編寫查詢。實質上,你正在做很多額外的工作,數據庫可以爲你做。 你的方法(作秀 - 不好SQL):

SELECT * FROM makes, models, products WHERE make_id = 5 

你沒有考慮到的關係(除非蛋糕自動神奇地理解表之間的關係)

你可能尋找將這些東西連接在一起的東西:

SELECT models.title FROM models 
INNER JOIN products 
    ON products.model_id = models.model_id 
    AND products.make_id = 5 

希望這是一個正確方向的微調?

0

所有不同的Make-> find()和Model-> find()調用都是完全獨立的。即使Make-> Model-> find()與Model-> find()相同,Cake也不會以任何方式記住或考慮您在其他模型中已經找到的內容。您要查找的是一樣的東西:

$this->Product->find('all', array('conditions' => array('make_id' => 5))); 
+0

好吧,我知道了,但是,我有品牌和型號之間的n ... N的關係。請問我寫的所有n ... N條件下,像makes.id = make_models.make_id和make_models.model_id = models.id ......等等......我的意思是...有一個HABTM ......可我用那個? – 2008-09-22 13:55:12

0

退房設置::提取物()用於從$這個 - > Make->找到()

結果得到的模型標題的列表方法
1

從您的評論中判斷,您所要求的是如何從某個模型中獲得結果,其中的條件在HABTM相關模型中。即你通常會用原始SQL中的JOIN語句來做這件事。
目前這是Cake的幾個弱點之一。有不同的策略來解決這個問題。

  • 有相關的B型迴歸模型A可能的候選人的所有ID,然後做了第二次查詢的型號AIE:

    $this->ModelB->find('first', array('conditions' => array('field' => $condition))); 
    array(
        ['ModelB'] => array(...), 
        ['ModelA'] => array(
         [0] => array(
          'id' => 1 
         ) 
    ) 
    

    現在你有屬於MODELA的所有ID數組到符合您的條件的ModelB,您可以使用Set :: extract()輕鬆提取這些條件。基本上相當於SELECT model_a.id FROM model_b JOIN model_a WHERE model_b.field = xxx。接下來,您找MODELA:

    $this->ModelA->find('all', array('conditions' => array('id' => $model_a_ids))); 
    

    這將產生SELECT model_a.* FROM model_a WHERE id IN (1, 2, 3),這是做JOIN語句的一種迂迴的方式。如果你需要一個以上的相關模型的條件下,重複,直到你有MODELA所有的ID,SQL將使用所有的IDS(WHERE id IN (1, 2, 3) AND id IN (3, 4, 5))的交叉點。

  • 如果你只需要在ModelB一個條件,但要檢索MODELA,只需搜索ModelB。 Cake會爲你自動檢索相關的ModelAs(見上文)。你可能需要再次Set :: extract(),但這可能已經足夠了。

  • 您可以用上面的方法,並與Containable behaviour結合起來,並得到了結果的更多控制。

  • 如果一切都失敗或上述方法產生的開銷過大,您仍然可以使用$this->Model->query()編寫自己的原始SQL。如果你堅持Cake SQL標準(正確命名錶FROM model_as AS ModelA)Cake仍然會正確地後處理你的結果。

希望這會讓您朝正確的方向發展。