2009-10-30 23 views
0

我正在處理從外部(並且完全不可更改)源導入數據的應用程序。我會簡化一些表格來解釋問題。下面是帶有主鍵的表格。使用CakePHP中沒有單個外鍵的模型

invoices  (doc_number, date_printed, batch_number) 
headers  (doc_number, date_printed, batch_number) 
deliveries (doc_number, date_printed, batch_number) 
transactions (doc_number, date_printed, batch_number, line_number) 
messages  (doc_number, date_printed, batch_number, line_number) 

所以你可以看到,發票,頁眉和交付有一對1的關係。發票到交易和發票到消息是一對多的。

在將這些表導入到我自己的數據庫中時,我已將現有主鍵更改爲唯一鍵,並在每個表上添加了auto_incrementing字段(id)。

現在問題是在Cake中設置關係,因爲它根本不處理組合鍵。我已經能夠得到這樣工作一到一對一的關係:

class Invoice extends AppModel { 
    public $name = "Invoice" 
     , $hasOne = array(
      "Header" => array(
       'foreignKey' => false, 
       'conditions' => array(
        "Invoice.doc_number = Header.doc_number", 
        "Invoice.date_printed = Header.date_printed", 
        "Invoice.batch_number = Header.batch_number" 
       ) 
      ) 
     ) 
    ; 
} 

而且這工作,因爲一到一個關係在一個去質疑一個大LEFT JOIN。嘗試使用與一對多關係相同的方法(例如,使用發票和交易)將會死亡,因爲Cake會執行兩個查詢:第一個查找所有匹配的發票,然後第二個查找具有相應外部的所有交易從第一次查詢的結果一致的關鍵:(這裏是它試圖運行簡化查詢)

SELECT `Transaction`.* FROM `transactions` AS `Transaction` 
WHERE `Invoice`.`doc_number` = `Transaction`.`doc_number` 
AND `Invoice`.`date_printed` = `Transaction`.`date_printed` 
AND `Invoice`.`batch_number` = `Transaction`.`batch_number` 

你可以看到,它不加入到這樣的發票查詢死亡。

有關我如何完成這項工作的任何想法?

回答

1

最糟糕的情況下,您可以使用hasMany relationship的finderQuery參數。它允許您完全覆蓋查詢。

您可能還可以添加一個將相關數據字段合併爲一個的唯一標識字段。 UPDATE語句可以修復現有數據,並且可以設置TRIGGER以在添加或更改新記錄時更新新記錄,前提是您的數據庫支持觸發器。

編輯:有了其他所有的複雜性,你可能會更好地跳過hasMany關係,並在單獨的find()中獲取Transaction記錄。如果你必須這樣做非常多的地方,你總是可以把它包在一個函數在發票模型像這樣的:

<?php 
class Invoice extends AppModel() { 
    ... 

    function getInvoice($conditions) { 
     $invoice = $this->find('first', compact('conditions')); 

     $conditions = array(
      'Transaction.doc_number' => $invoice['Invoice']['doc_number'], 
      'Transaction.date_printed' => $invoice['Invoice']['date_printed'], 
      'Transaction.batch_number' => $invoice['Invoice']['batch_number']); 
     $invoice['transactions'] = $this->Transaction->find('all', compact('conditions')); 

     return $invoice; 
    } 
} 
?> 

如果您在模型中使用函數那樣,不要忘記,發票會需要一個定義的關係到事務,即使你不直接使用它,以便$ this-> Transaction被定義。另外,如果你希望以hasMany關係的方式返回數據,你總是可以添加一個foreach循環來重組它們。

更新 還有一個SimpleResults behavior in the Cake Bakery,將允許返回容易從其他表這些結果在常規的hasMany關聯的格式。

+0

所以我告訴蛋糕,這是一個HABTM當它是真的「的hasMany」?關於這些數據真的非常棒的新聞(對我來說)是它在應用程序中是隻讀的,所以更新和觸發器不會成爲問題。 – nickf 2009-10-30 10:02:30

+0

不,這應該是hasMany,只是finderQuery。我第一次通過它誤讀了一些東西。 – Jason 2009-10-30 11:04:57

相關問題