Introduzione
Tra gli operatori meno conosciuti di PHP, ma molto utili nella pratica, troviamo l’operatore spaceship, rappresentato da <=>. Il suo nome richiama la forma di una navicella spaziale e deriva dal fatto che confronta due valori restituendo una direzione precisa del confronto.
L’operatore <=> confronta il valore a sinistra con quello a destra e restituisce:
-1se il primo valore è minore del secondo;0se i due valori sono equivalenti;1se il primo valore è maggiore del secondo.
Questo comportamento è particolarmente utile quando si devono ordinare array con usort(), perché la funzione di confronto richiesta da PHP deve restituire proprio un numero negativo, zero o positivo. Invece di scrivere diversi blocchi if, possiamo quindi usare direttamente l’operatore spaceship.
È importante non confonderlo con un normale operatore di uguaglianza o con un confronto booleano. L’espressione $a <=> $b non restituisce true o false, ma un valore numerico che indica il risultato del confronto.
Codice completo
<?php
$prodotti = [
[
´nome´ => ´Tastiera meccanica´,
´prezzo´ => 89.90,
],
[
´nome´ => ´Mouse wireless´,
´prezzo´ => 29.90,
],
[
´nome´ => ´Monitor 27 pollici´,
´prezzo´ => 249.00,
],
[
´nome´ => ´Webcam Full HD´,
´prezzo´ => 59.90,
],
];
// Ordina i prodotti dal prezzo più basso al prezzo più alto.
usort($prodotti, function (array $prodottoA, array $prodottoB): int {
return $prodottoA[´prezzo´] <=> $prodottoB[´prezzo´];
});
echo "<h2>Prodotti ordinati per prezzo crescente</h2>";
echo "<ul>";
foreach ($prodotti as $prodotto) {
echo "<li>";
echo htmlspecialchars($prodotto[´nome´], ENT_QUOTES, ´UTF-8´);
echo " - ";
echo number_format($prodotto[´prezzo´], 2, ´,´, ´.´) . " euro";
echo "</li>";
}
echo "</ul>";
// Lo stesso ordinamento in senso decrescente.
// Basta invertire i due operandi.
usort($prodotti, function (array $prodottoA, array $prodottoB): int {
return $prodottoB[´prezzo´] <=> $prodottoA[´prezzo´];
});
echo "<h2>Prodotti ordinati per prezzo decrescente</h2>";
echo "<ul>";
foreach ($prodotti as $prodotto) {
echo "<li>";
echo htmlspecialchars($prodotto[´nome´], ENT_QUOTES, ´UTF-8´);
echo " - ";
echo number_format($prodotto[´prezzo´], 2, ´,´, ´.´) . " euro";
echo "</li>";
}
echo "</ul>";
// Esempi semplici di confronto.
var_dump(3 <=> 8); // int(-1)
var_dump(5 <=> 5); // int(0)
var_dump(10 <=> 2); // int(1) Spiegazione
Il risultato dell’operatore
Consideriamo tre espressioni:
<?php
echo 4 <=> 9; // -1
echo 7 <=> 7; // 0
echo 12 <=> 3; // 1 Nel primo caso, 4 è minore di 9, quindi il risultato è negativo. Nel secondo caso i valori sono uguali e viene restituito 0. Nell’ultimo caso, 12 è maggiore di 3, quindi il risultato è positivo.
Il valore restituito non deve essere necessariamente esattamente -1 o 1 in ogni tipo di confronto interno: ciò che conta è il segno del risultato. Tuttavia, con numeri e confronti comuni PHP restituisce normalmente questi valori.
Ordinamento crescente e decrescente
La funzione usort() riceve un array e una funzione di confronto. La funzione viene chiamata più volte per confrontare coppie di elementi. Se restituisce un valore negativo, il primo elemento viene considerato precedente al secondo; se restituisce zero, i due elementi sono equivalenti per l’ordinamento; se restituisce un valore positivo, il primo elemento viene dopo il secondo.
Per ordinare in modo crescente si scrive:
return $a[´valore´] <=> $b[´valore´]; Per invertire l’ordine è sufficiente scambiare gli operandi:
return $b[´valore´] <=> $a[´valore´]; Ordinare per più criteri
Un caso realistico consiste nell’ordinare prima per prezzo e, quando due prezzi coincidono, per nome. Possiamo combinare lo spaceship con un secondo confronto:
<?php
usort($prodotti, function (array $a, array $b): int {
$confrontoPrezzo = $a[´prezzo´] <=> $b[´prezzo´];
if ($confrontoPrezzo !== 0) {
return $confrontoPrezzo;
}
return $a[´nome´] <=> $b[´nome´];
}); In questo modo il nome viene usato soltanto quando i prezzi sono uguali.
Best practice
- Usa tipi omogenei: confronta numeri con numeri e stringhe con stringhe. Evita array in cui lo stesso campo contiene talvolta un numero e talvolta una stringa non numerica.
- Indica i tipi delle funzioni: dichiarare
arrayper i parametri eintper il risultato rende il codice più leggibile e facilita l’individuazione degli errori. - Gestisci i valori mancanti: prima di confrontare un campo come
prezzo, assicurati che esista e abbia un valore valido. - Non usare lo spaceship per verificare solo l’uguaglianza: se vuoi sapere se due valori sono uguali, un confronto esplicito è più chiaro.
- Usa funzioni dedicate per casi complessi: per ordinamenti con regole articolate, estrai la logica in una funzione nominata invece di creare callback troppo lunghe.
- Ricorda che
usort()reindicizza l’array: se le chiavi originali sono importanti, valuta funzioni di ordinamento che le preservano, comeuasort().
Riepilogo
L’operatore spaceship <=> confronta due valori e restituisce un numero negativo, zero o positivo. È una soluzione compatta e leggibile per costruire funzioni di ordinamento con usort(), soprattutto quando si lavora con array di record, prodotti, utenti o risultati di query.
La forma principale è:
$a <=> $b Per un ordinamento crescente si confrontano normalmente i valori; per un ordinamento decrescente si scambiano gli operandi. Quando servono più criteri, si può eseguire un secondo confronto solo se il primo restituisce zero.
Approfondisci con risorse ufficiali
- Manuale PHP: pagina ufficiale sugli operatori di confronto, inclusa la documentazione dell’operatore spaceship.
- Manuale PHP: documentazione della funzione
usort()per ordinare array tramite una funzione di confronto personalizzata. - Manuale PHP: documentazione della funzione
uasort()per ordinare mantenendo le chiavi associate agli elementi. - PHP Language Reference: sezione ufficiale dedicata agli operatori e alle regole di confronto tra valori.
