So che questo è un vecchio thread, ma mi sono imbattuto in un altro caso di oggi che potrebbe trarre beneficio da un altro approccio. Ho avuto un caso in cui volevo utilizzare una chiave specifica in modo da poter astrarre la funzione di supporto reale. Ciò ha portato a trovare una versione che utilizza una funzione wrapper per restituire una funzione anonima che utilizza la parola di comando 'use' per fornire il nome della chiave usata per ordinare nella mia classe. (nel mio caso, è una chiave in una proprietà su una classe [nested] che viene assegnata a una delle proprietà della classe in cui sto facendo l'ordinamento, cioè sto ordinando le istanze in base a una proprietà in un'istanza di 'dimensioni' assegnato ad una proprietà di "articoli" e vuole essere in grado di ordinarli per larghezza, altezza, lunghezza o peso, ad esempio). Quindi per ottenere la funzione per la richiamata, è sufficiente chiamare questa funzione wrapper con il nome della chiave che si desidera utilizzare per ordinare il risultato:
/**
* list of items
*
* @var Item[]
*/
public $items;
/**
* @param string $key
* @return \Closure
*/
private static function keySort($key) {
return function ($ia, $ib) use ($key) {
if($ia->dimensions->$key == $ib->dimensions->$key) return 0;
return ($ia->dimensions->$key < $ib->dimensions->$key) ? -1 : 1;
};
}
/**
* return the list of items in the items array sorted by the value
* of the property specified by $key
*
* @param string $key
* @return Item[]
* @throws \Exception
*/
public function sortItemsByKey($key)
{
if(in_array($key, array('width', 'length', 'height', 'weight',))) {
return usort($this->items, static::keySort($key));
} else
throw new \Exception(__METHOD__ . ' invalid sort key!');
}
Questo mi permette di chiamarla locale utilizzando statica :: o di auto: : (presumibilmente, potrei anche avvolgerlo come una funzione non statica in questo caso poiché l'unica cosa di cui sono preoccupato è ricevere la chiamata ma la funzione è stata restituita) Un altro vantaggio che ho presto scoperto è che l'oggetto delle mie dimensioni ha anche un po 'di calcolato 'campi come circonferenza, volume e peso dimensionale. Ma un problema è che il peso dimensionale varia a seconda che tu stia spedendo un articolo a livello nazionale o internazionale, quindi devo dire alla mia funzione 'calculateDimensionalWeight' se deve utilizzare il valore per la spedizione internazionale o meno.Bene, usando questo metodo, posso farlo passando semplicemente un parametro addizionale alla funzione wrapper e aggiungendo il parametro aggiuntivo alle variabili use. Dal momento che ho anche bisogno di assicurarsi che questi valori sono stati calcolati prima di fare qualsiasi confronto, posso scattare che nella mia funzione in base alla chiave:
/**
* @param string $key
* @param bool $intl // only used for dimensional weight
* @return \Closure
*/
private static function keySort($key,$intl=false) {
return function ($ia, $ib) use ($key,$intl) {
switch($key) {
case 'girth':
$ia->dimensions->calculateGirth();
$ib->dimensions->calculateGirth();
break;
case 'dimweight':
$ia->dimensions->calculateDimensionalWeight($intl);
$ib->dimensions->calculateDimensionalWeight($intl);
break;
case 'volume':
$ia->dimensions->calculateVolume();
$ib->dimensions->calculateVolume();
break;
}
if($ia->dimensions->$key == $ib->dimensions->$key) return 0;
return ($ia->dimensions->$key < $ib->dimensions->$key) ? -1 : 1;
};
}
/**
* return the list of items in the items array sorted by the value
*
* @param string $key
* @param bool $intl (only used for dimensional weight sorts on international shipments)
* @return Item[]
* @throws \Exception
*/
public function sortItemsByKey($key,$intl=false)
{
if(in_array($key, array('value','collect', 'width', 'length', 'height', 'weight', 'girth', 'dimweight', 'volume'))) {
return usort($this->items, static::keySort($key,$intl));
} else
throw new \Exception(__METHOD__ . ' invalid sort key!');
}
NOTA: il calcolo dei valori in questo modo crea in testa, come tutti, ma il primo e gli ultimi elementi in qualsiasi elenco verranno calcolati tecnicamente due volte, che è ridondante, ma in questo caso le mie liste non sono lunghe e in alcuni casi, ho bisogno di confrontare due elementi quando si effettua l'ordinamento bin, quindi è ancora preferibile. Per dataset di grandi dimensioni, sarebbe probabilmente più saggio pre-calcolare valori esterni al metodo di ordinamento.
In qualche modo penso che tu abbia perso [questa risposta] (http://stackoverflow.com/a/6054036/1229023) durante la ricerca di problemi simili, vero? – raina77ow
L'ho visto, ma il nome della classe non ha funzionato. $ questo fa. – Marinus
Hai reso statica questa funzione prima di provare a chiamarla con il nome della classe? – raina77ow