Ordinare i risultati con i campi dei model associati ricorsivamente: ORDER BY FIELD.

Il titolo è un po’ contorto, ma non sono riuscito a trovare di meglio.
L’esigenza nasce quando voglio ordinare il risultato di una query che vede interessati vari Model utilizzando un determinato campo per l’ordinamento.
Faccio l’esempio: ho i seguenti model e le seguenti relazioni.

Continent hasMany Country
Country hasMany News

Il modello Continent ha un campo ‘order’ che serve a mantenere un determinato ordine di presentazione per i continenti.
Voglio ottenere una lista di News ordinate per Continent.order.
Poichè il model News ha molte relazioni con altri model (Tag, Area, Comment, ecc. ecc. ), utilizzo il behavior Containable.
A questo punto non è sufficente impostare l’elemento ‘order’ a ‘Continent.order ASC’, perchè la query restituisce un errore. Infatti CakePHP esegue prima una query per ricavare l’elenco delle News e per ogni News ricavata esegue una successiva query per determinare il continente relativo al country.

//
$this->Continent->find('all', array('order' => 'Continent.name')) // Restituisce un errore nell query SQL
//
 

SOLUZIONI
Una soluzione generica che risolve ampiamente il problema è impiegare questo behavior suggeritomi da fzanardo nel forum, ma che non ho personalmente provato.

Una soluzione light invece è la seguente:

// estraggo gli di dei continenti ordinati in base al campo 'order'
$continents = array_keys($this->News->Country->Continent->find('list',array('fields'=>array('id','order'),'recursive'=>-1,'order'=>'order')));

$lista = $this->News->find('all',array(	'conditions'=>$conditions,
												'contain'=>array(
															'Area',
															'Country'=>array('Continent'),	
														),
												'order' => array('FIELD(Country.continent_id,'.implode(',',$continents).')')

ORDER BY FIELD(Country.continent_id, 1,4,3,6,5,2) sarà l’impostazione del’ordine che consentirà di ottenere l’ordine voluto, mantenendo la query leggera.
Riferimento: http://cakebaker.42dh.com/2008/06/10/order-by-field/

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.