2012-12-31 13 views
11

CakePHP za Model::afterFind() zwrotna wygląda następująco:

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

Zgodnie z dokumentacją:

Parametr $primary wskazuje, czy obecny model był modelem, że zapytanie pochodzi lub czy ten model został zapytany jako stowarzyszenie. Jeśli model jest sprawdzany jako skojarzenie, format $results może się różnić.

one może różnić, ale eksperyment pokazuje, że nie zawszeróżnią. O ile mogę powiedzieć, parametr $primary nie jest tak naprawdę użyteczny. Jeśli jest ustawiony na false, możesz uzyskać nie spłaszczoną strukturę danych, więc możesz skończyć z komunikatem o błędzie "Nie można użyć przesunięcia łańcucha jako tablicy".

Chociaż nie próbowałem tego jeszcze, moja myśl na podstawie dokumentacji było zignorować flagę $primary całkowicie i po prostu sprawdzić dane:

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; 
} 

To hackish a ja się nie podoba, ale wydaje się bardziej przydatne niż $primary.

wyraźnie stwierdził, moje pytania są następujące:

  1. Co jest flaga $primary rzeczywiście przydatna?
  2. Czy mam rację, że jest to nie przydatne do określenia struktury macierzy $results, czy też coś tam przeoczyłem?

Odpowiedz

11

Rzeczywiście parametr $primary wydaje się być użyteczne tylko w ostrzeżenia o wypadkach gdzie format $results jest nieprzewidywalny. Nie jest to przydatne przy określaniu formatu $results.

Więcej informacji tutaj: https://groups.google.com/forum/?fromgroups=#!topic/cake-php/Mqufi67UoFo

Rozwiązanie oferowane jest do sprawdzenia !isset($results[$this->primaryKey]) aby zobaczyć, co jest w formacie $results. To także trochę hack, ale prawdopodobnie lepsze niż sprawdzanie klucza "0".

Rozwiązanie I ostatecznie wymyślił żeby zrobić coś takiego:

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); 
} 

Zmniejsza powielania kodu, ponieważ nie trzeba pisać logiki zmianom pola dwukrotnie (raz na tablicę i raz na nie tablica).

Być może uda Ci się całkowicie uniknąć odniesień, zwracając po prostu $resultsArray na końcu metody, ale nie byłem pewien, jakie problemy mogą spowodować, że CakePHP (lub inna klasa rodzica) spodziewa się, że w pewnym sensie $results został przekazany. Plus w ten sposób nie ma narzutu na kopiowanie tablicy $results.

+1

Dzisiaj wpadł w ten problem. Czasami zestaw $ result jest tablicą wielowymiarową, czasami nie jest. Czuję, że to powinien być dość duży problem. – vinhboy

+0

Wow, mógłbym cię pocałować. To właśnie uratowało mnie po uderzeniu w głowę przez 4 godziny. – bowlerae

-2

odpowiedzi w książce ...

Podstawowym parametrem $ wskazuje, czy obecny model był model, który pochodzi zapytanie lub czy ten model została zapytaliśmy jako stowarzyszenie. Jeśli model jest sprawdzany jako stowarzyszenie , format wyników $ może się różnić;

Kod, który oczekuje, że $ primary będzie prawdą, prawdopodobnie dostanie "Nie można użyć przesunięcia łańcucha jako tablicy" błąd krytyczny z PHP, jeśli użyto rekurencyjnego finda .

Zatem może to być przydatne w pewnych sytuacjach do przetwarzania logicznego i może mogłyby być użyte do pukanie efekt w swoim $ wyników

+4

Możesz zauważyć, że zacytowałem tę samą sekcję dokumentacji. Jednakże, jak powiedziałem w moim pytaniu, jeśli '$ primary' jest ustawione na' false', co nie musi oznaczać, że '$ results' będzie sformatowany inaczej. Jak mówią docs, "format' $ wyników' ** może ** się różnić. " Ale też może nie. Eksperymentacja to potwierdza. – eaj

0

Wpadłem na ten problem. Przyjęta odpowiedź działa dobrze. Musiałem jednak dokonać drobnej korekty. Jeśli chcesz zmodyfikować pole, na przykład skonstruuj w pełni kwalifikowaną nazwę pliku z logo, lepiej jest utworzyć nowe pole jako "return parent :: afterFind ($ results, $ useless);" zrobi to dwa razy, jeśli wyszukiwanie modelu zostanie wywołane z innego modelu.

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

Jeśli nie zawsze można polegać na primaryKey będącego na liście pól i wiesz klucz, którego szukasz, możesz uciec z czymś nieco bardziej proste. Oto przykład:

/** 
* 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; 
} 
Powiązane problemy