2012-12-31 57 views
11

CakePHP的Model::afterFind()回調的樣子:

afterFind(array $results, boolean $primary = false) 

根據文檔:

$primary參數指示當前模式是否是該查詢起源於或者判斷這種模式的模型被質疑爲一個協會。如果模型被查詢爲關聯,則$results的格式可能不同。

他們可以不同,但實驗表明,他們並不總是不同。據我所知,$primary參數實際上並不是那麼有用。如果設置爲false,則可能會或可能不會得到一個扁平的數據結構,因此您可能會或可能不會收到令人畏懼的「無法使用字符串偏移量作爲數組」的錯誤消息。

雖然我還沒有嘗試過,基於文檔我的想法是完全忽略$primary標誌,只是檢查數據:

public function afterFind($results, $primary = false) { 
    if (array_key_exists(0, $results) { 
    // operate on $results[0]['User']['fieldname'] 
    } else { 
    // operate on $results['fieldname'] 
    } 
    return $results; 
} 

這是hackish的,我不喜歡它,但它似乎比$primary更有用。

明確指出,我的問題是:

  1. 什麼是$primary標誌實際上有用嗎?
  2. 我是否確定這是而不是對確定$results陣列的結構很有用,還是我錯過了某些東西?

回答

11

事實上,$primary參數似乎只能是有用的,警告你的案件$results的格式是不可預知的。這對確定$results的格式沒有用。

點擊此處瞭解詳情:https://groups.google.com/forum/?fromgroups=#!topic/cake-php/Mqufi67UoFo

的解決方案提供有檢查!isset($results[$this->primaryKey])看到$results是什麼格式。這也是一種破解,但可以說比檢查關鍵字'0'更好。

我最終想出瞭解決的辦法是做這樣的事情:

public function afterFind($results, $useless) { 

    // check for the primaryKey field 
    if(!isset($results[$this->primaryKey])) { 
     // standard format, use the array directly 
     $resultsArray =& $results; 
    } else { 
     // stupid format, create a dummy array 
     $resultsArray = array(array()); 
     // and push a reference to the single value into our array 
     $resultsArray[0][$this->alias] =& $results; 
    } 

    // iterate through $resultsArray 
    foreach($resultsArray as &$result) { 
     // operate on $result[$this->alias]['fieldname'] 
     // one piece of code for both cases. yay! 
    } 

    // return $results in whichever format it came in 
    // as but with the values modified by reference 
    return parent::afterFind($results, $useless); 
} 

這樣可以減少代碼的重複,因爲你沒有寫你的領域改變邏輯兩次(一次爲一個數組,並一次非陣列)。

您可以通過在方法結尾處返回$resultsArray來完全避免引用這些東西,但我不確定在CakePHP(或其他父類)期望的方式中可能會導致哪些問題$results它被傳入。此外,這種方式沒有複製$results陣列的開銷。

+1

今天遇到這個問題。有時$結果集是一個多維數組,有時不是。我覺得這應該是一個很大的問題。 – vinhboy

+0

哇,我可以吻你。這只是在我的頭撞了4個小時後才救了我。 – bowlerae

-2

答案在書...

的$主參數指示當前模式是否是 該查詢起源於或者判斷這種模式 模型被質疑爲協會。如果某個模型被查詢爲關聯 ,$ results的格式可能不同;

希望$ primary成爲true的代碼可能會得到一個「不能使用 字符串偏移量作爲數組」的PHP致命錯誤,如果遞歸查找使用 。

因此它可以在邏輯處理某些情況下非常有用,可能可以用來對影響敲到$結果

+4

您可能會注意到我引用了同一部分的文檔。然而,正如我在我的問題中所說的,如果'$ primary'設置爲'false',並不一定意味着'$ results'將被格式化爲任何不同。正如文檔所說,「$ results' **的格式可以**不同。」但是,再一次,它可能不會。實驗支持這一點。 – eaj

0

我遇到了這個問題。接受的答案很好。但是,我不得不做一個小調整。如果你想修改一個字段,例如用logo來構造一個完整的文件名,最好創建一個新的字段,比如「return parent :: afterFind($ results,$ useless);」如果模型查找是從其他模型調用的,則會執行兩次。

foreach($resultsArray as &$result) { 
     // operate on $result[$this->alias]['fieldname'] 
     // one piece of code for both cases. yay! 

     // Added logoFull instead of modifying logo 
     if(isset($result[$this->alias]['logo'])){ 
      $result[$this->alias]['logoFull'] = Configure::read('urlImg') . 'logos' . DIRECTORY_SEPARATOR . 
       'carrier' . DIRECTORY_SEPARATOR . $result[$this->alias]['logo']; 
     } 
    } 
1

如果你不能總是依靠primaryKey在字段列表是,你知道你正在尋找的鍵,就可以擺脫一些更簡單。以下是一個示例:

/** 
* Decrypt password 
* 
* @see Model::afterFind() 
*/ 
public function afterFind($results, $primary = false) {   
    if (!empty($results['password'])) { 
     $results['password'] = Security::rijndael($results['password'], Configure::read('encrypt.key'), 'decrypt'); 
     return $results; 
    } 

    foreach ($results as &$r) { 
     if (!empty($r[$this->alias]['password'])) { 
      $r[$this->alias]['password'] = Security::rijndael($r[$this->alias]['password'], Configure::read('encrypt.key'), 'decrypt'); 
     } 
    } 
    return $results; 
} 
相關問題