PHP tiene funciones de ordenación con criterio fijo (sort(), asort(), ksort()...) y funciones de ordenación con criterio personalizable. usort() ordena un array usando un callback que tú defines; uasort() hace lo mismo pero preserva las asociaciones clave-valor; y uksort() ordena por las claves. Son las tres que necesitas cuando los criterios de ordenación van más allá del orden alfabético o numérico simple.
usort(): ordenar por criterio propio
<?php usort(array &$array, callable $callback): bool ?>
El callback recibe dos elementos y debe devolver un entero negativo, cero o positivo según si el primero va antes, en la misma posición o después que el segundo. El operador spaceship (<=>, disponible desde PHP 7) simplifica esto enormemente:
<?php
$productos = [
['nombre' => 'Zapatillas', 'precio' => 89.90],
['nombre' => 'Camiseta', 'precio' => 19.90],
['nombre' => 'Pantalón', 'precio' => 39.90],
];
// Orden ascendente por precio
usort($productos, fn($a, $b) => $a['precio'] <=> $b['precio']);
foreach ($productos as $p) {
echo $p['nombre'] . ': ' . $p['precio'] . "n";
}
// Camiseta: 19.9
// Pantalón: 39.9
// Zapatillas: 89.9
?>
Ordenar por múltiples campos
Cuando el primer campo tiene empate, el spaceship encadenado con || resuelve el desempate con el siguiente campo:
<?php
$empleados = [
['nombre' => 'Carlos', 'departamento' => 'IT', 'salario' => 3200],
['nombre' => 'Ana', 'departamento' => 'IT', 'salario' => 3800],
['nombre' => 'Marta', 'departamento' => 'Ventas', 'salario' => 2900],
['nombre' => 'Luis', 'departamento' => 'IT', 'salario' => 3200],
];
// Ordenar por departamento, luego por salario descendente, luego por nombre
usort($empleados, function($a, $b) {
return $a['departamento'] <=> $b['departamento']
?: $b['salario'] <=> $a['salario'] // descendente: b <=> a
?: $a['nombre'] <=> $b['nombre'];
});
?>
Ordenar objetos por propiedad
<?php
class Articulo {
public function __construct(
public string $titulo,
public DateTime $fecha,
public int $visitas
) {}
}
$articulos = [
new Articulo('PHP Arrays', new DateTime('2024-03-10'), 1240),
new Articulo('PHP Strings', new DateTime('2024-05-22'), 876),
new Articulo('PHP 8.4', new DateTime('2024-04-01'), 3150),
];
// Ordenar por visitas descendentes
usort($articulos, fn($a, $b) => $b->visitas <=> $a->visitas);
foreach ($articulos as $art) {
echo "{$art->titulo}: {$art->visitas} visitasn";
}
// PHP 8.4: 3150 visitas
// PHP Arrays: 1240 visitas
// PHP Strings: 876 visitas
?>
uasort() y uksort()
<?php // uasort: preserva claves, útil con arrays asociativos $inventario = ['camiseta' => 45, 'pantalon' => 12, 'zapatillas' => 0, 'chaqueta' => 8]; uasort($inventario, fn($a, $b) => $b <=> $a); // descendente por valor print_r($inventario); // Array ( [camiseta] => 45 [pantalon] => 12 [chaqueta] => 8 [zapatillas] => 0 ) // uksort: ordena por las propias claves $config = ['puerto' => 3306, 'host' => 'localhost', 'charset' => 'utf8mb4']; uksort($config, fn($a, $b) => strcmp($a, $b)); print_r($config); // Array ( [charset] => utf8mb4 [host] => localhost [puerto] => 3306 ) ?>
Ordenación estable en PHP 8
Desde PHP 8.0, todas las funciones de ordenación (incluidas usort, uasort y uksort) son estables: elementos considerados iguales por el comparador mantienen su orden relativo original. En PHP 7 el orden de los empates era indefinido, lo que podía producir resultados distintos entre ejecuciones.
La documentación oficial de usort() incluye el historial de la estabilidad de ordenación y los cambios de comportamiento respecto a PHP 7.
