2014-01-30 25 views
0

我有兩種情況,其中兩個類似的查詢被做出來,並且在一種情況下,關聯模型的虛擬字段的代碼不會生成到sql查詢語句,因此沒有找到。在類似的查詢中的虛構模型的虛擬領域,但有時不構建到sql查詢

在數據庫: *兩個主表(hospitalshotels) *一個引用表contacts *主表具有指向所述接觸表各個領域。對於醫院例如一個director_contact_id和一個janitor_contact_id。對於酒店director_contact_idconcierge_contact_id

在CakePHP *的Hospital模型有兩個屬於關聯關係DirectorContactJanitorContact *的Hotel模型有兩個屬於關聯關係DirectorContactConciergeContact *觸點有一個虛擬場full_name,是像CONCAT(…)

在HospitalController ,無論何時我需要將聯繫人的某個數據綁定到醫院數據,我可以這樣做:

$contain = array(); 
… 
$contain['DirectorContact'] = array('fields' => array('id','full_name')); 
… 
$this->Hospital->find('all', array(
    … 
    'contain' => $contain, 
    … 
)); 

生成的SQL代碼包含

CONCAT(…) AS DirectorContact__full_name 

然而,同樣的沒有在HotelController工作。在那裏,我也這樣做:

$contain['DirectorContact'] = array('fields' => array('id','full_name')); 

如果我

debug($this->Hotel->DirectorContact->virtualFields); 

我得到

array(
    'full_name' => 'CONCAT(…)' 
) 

但是當我運行的操作,我得到一個SQL錯誤,指出該領域full_name是未知的。我可以看到,在生成的CONCAT(…) AS DirectorContact__full_name SQL查詢丟失。

在這兩種情況下,聯繫人表都被多次引用,至少與不同的別名有關聯。所以我不確定爲什麼CakePHP在一個案例中生成正確的查詢,而在另一個案例中卻沒有。

當然,查找語句更復雜,比我在這裏陳述的更多的包含,連接和字段。

問題1:有誰知道什麼可能會觸發CakePHP放棄爲關聯模型的虛擬域生成代碼?

我讀過可容納的行爲有點微妙,在某些情況下最好使用連接。

所以在虛擬領域不起作用的一種情況下,我使用連接而不是包含。然而是不是生成的虛擬領域,所以我做了明確兩個assiciations:

$fields[] = 'DirectorContact.id'; 
$fields[] = 'CONCAT(…) AS `DirectorContact__name_or_company`'; 
$fields[] = 'ConciergeContact.id'; 
$fields[] = 'CONCAT(…) AS `ConciergeContact__name_or_company`'; 

如果我調試查詢的結果:

array(
    'Hotel' => array(
     'id' => '123', 
    ), 
    'DirectorContact' => array(
     'id' => '456', 
     'name_or_company' => 'Some name' 
    ), 
    (int) 0 => array(
     'ConciergeContact__name_or_company' => 'Some other name', 
    ), 
    'ConciergeContact' => array(
     'id' => '789' 
    ), 
) 

所以對於第一關聯AUTOMAGIC作品和CakePHP寫入虛擬領域DirectorContact__name_or_company的內容到關聯數組的DirectorContact一部分,但其它獲得的放置到「一般」的一部分,由鍵0

引用計算字段但是,什麼是更在teresting:如果我交流字段定義的模型引用的順序

$fields[] = 'ConciergeContact.id'; 
$fields[] = 'CONCAT(…) AS `ConciergeContact__name_or_company`'; 
$fields[] = 'DirectorContact.id'; 
$fields[] = 'CONCAT(…) AS `DirectorContact__name_or_company`'; 

結果是

array(
    'Hotel' => array(
     'id' => '123', 
    ), 
    'ConciergeContact' => array(
     'id' => '789' 
    ), 
    (int) 0 => array(
     'ConciergeContact__name_or_company' => 'Some other name', 
     'DirectorContact__name_or_company' => 'Some name', 
    ), 
    'DirectorContact' => array(
     'id' => '456', 
    ), 
) 

所以現在AUTOMAGIC完全不工作了,和兩個虛擬字段wqritten成一般部分。

問題2:有誰知道這個原因,以及如何讓CakePHP的automagic適用於所有情況?

(使用2.4.3版本)

回答

1

挖掘到CakePHP的代碼後,我找到了原因。

如果爲查詢定義字段選項,則不會創建virtualFields(即使將它們添加到字段選項)。

在單位DboSource.php中有函數read(Model $model, $queryData = array(), $recursive = null)

該函數的代碼的一個片段:

if (!empty($queryData['fields'])) { 
    $bypass = true; 
    … 
} else { 
    … 
} 
$_associations = $model->associations(); 
… 
foreach ($_associations as $type) { 
    foreach ($model->{$type} as $assoc => $assocData) { 
     … 
     if ($model->useDbConfig === $linkModel->useDbConfig) { 
      if ($bypass) { 
       $assocData['fields'] = false; 
      } 
      if ($this->generateAssociationQuery($model, $linkModel, $type, $assoc, $assocData, $queryData, $external, $null) === true) { 
       … 
      } 
     } 
    } 
} 

SO時的字段選項被定義,那麼可變$bypass被設置爲真。再往下,在建立所有關聯模型的查詢代碼的情況下,當$bypass爲真時,關聯模型的字段定義被設置爲假。這顯然也會刪除虛擬域。

然後,當您在查詢的字段選項中包含該字段時,它將不會被找到。

合乎邏輯...