Ordenação de array de objetos em PHP: do iniciante ao avançado
\n\nImagine a seguinte situação: você está desenvolvendo uma loja virtual em PHP. Você tem um array de produtos, onde cada produto é um objeto com campos como price, name e rating. O usuário clica em "Ordenar por preço" e você precisa reorganizar esse array instantaneamente. Como fazer isso de forma correta e elegante? É exatamente sobre isso que vamos falar hoje.
O tópico ordenação de array de objetos por uma propriedade em PHP é uma das perguntas mais populares no Stack Overflow (com milhões de visualizações!). Não é surpresa: trabalhar com objetos é a base do PHP moderno, e saber ordenar dados de forma flexível é uma habilidade essencial. Vamos explorar do simples ao complexo, com exemplos práticos e explicações detalhadas.
\n\nPor que não posso simplesmente usar sort()?
\n\nIniciantes frequentemente tentam usar sort() ou rsort() em um array de objetos. E acabam recebendo um erro ou um resultado sem sentido. Por quê? Porque essas funções comparam elementos como valores simples (números ou strings), enquanto um objeto é uma estrutura complexa. O PHP não sabe por qual campo você deseja ordenar: nome, preço ou data. É necessário definir explicitamente a regra de comparação.
Para isso, existem as funções usort(), uasort() e uksort(). A letra "u" no nome significa "user-defined" — função de comparação definida pelo usuário. Nós mesmos escrevemos como comparar dois objetos.
Exemplo básico: ordenando usuários por idade
\n\nSuponha que temos uma classe User e um array de usuários:
class User {\n public $name;\n public $age;\n \n public function __construct($name, $age) {\n $this->name = $name;\n $this->age = $age;\n }\n}\n\n$users = [\n new User('Ana', 25),\n new User('João', 30),\n new User('Olga', 22),\n new User('Pedro', 28)\n];\n\nPrecisamos ordená-los por idade crescente. Vamos usar usort:
\n\nusort($users, function($a, $b) {\n return $a->age <=> $b->age;\n});\n\n// Resultado:\n// Olga (22), Ana (25), Pedro (28), João (30)\n\nObserve o operador spaceship ( <=> ) — ele foi introduzido no PHP 7.0 e torna o código incrivelmente conciso. Ele retorna -1, 0 ou 1, o que é perfeito para funções de comparação.
Entendendo o mecanismo do usort
\n\nA função usort() recebe dois argumentos:
- \n
- O array (passado por referência — o array original será modificado) \n
- Uma função callback que compara dois elementos \n
O callback deve retornar:
\n- \n
- Um número negativo (geralmente -1) — se o primeiro elemento for menor que o segundo \n
- 0 — se os elementos forem iguais \n
- Um número positivo (geralmente 1) — se o primeiro elemento for maior que o segundo \n
O operador spaceship faz isso automaticamente. Veja como seria a mesma ordenação sem ele:
\n\nusort($users, function($a, $b) {\n if ($a->age == $b->age) return 0;\n return ($a->age < $b->age) ? -1 : 1;\n});\n\nA diferença é clara: o operador <=> reduz 4 linhas a uma. Use-o sempre que sua versão do PHP for 7 ou superior.
Ordenação por strings: considerando maiúsculas/minúsculas e localidade
\n\nCom números é simples, mas strings exigem atenção. Vamos ordenar os mesmos usuários pelo nome:
\n\nusort($users, function($a, $b) {\n return strcmp($a->name, $b->name);\n});\n\n// Ou com spaceship:\nusort($users, function($a, $b) {\n return $a->name <=> $b->name;\n});\n\nMas há um detalhe: o spaceship diferencia maiúsculas de minúsculas. A string "apple" será considerada menor que "Banana", porque o código do caractere 'a' (97) é menor que 'B' (66). Para uma ordenação sem distinção de maiúsculas/minúsculas, use strcasecmp():
usort($users, function($a, $b) {
return strcasecmp($a->name, $b->name);
});
E para ordenação que respeite a localidade (como acentos em português), utilize setlocale() e strcoll():
setlocale(LC_ALL, 'pt_BR.utf8');
usort($users, function($a, $b) {
return strcoll($a->name, $b->name);
});
Mantendo a associação de chaves com uasort
Se você precisa manter a associação entre chaves e valores (como em um array associativo), use uasort() em vez de usort(). A diferença é que usort() reindexa o array numericamente, enquanto uasort() preserva as chaves originais.
$products = [
'produto_a' => new Product('Notebook', 3500),
'produto_b' => new Product('Mouse', 150),
'produto_c' => new Product('Teclado', 250)
];
uasort($products, function($a, $b) {
return $a->price <=> $b->price;
});
// As chaves 'produto_a', 'produto_b', 'produto_c' são preservadas
Ordenação decrescente
Para ordenar em ordem decrescente, basta inverter a comparação:
// Decrescente por idade
usort($users, function($a, $b) {
return $b->age <=> $a->age;
});
// Ou multiplique por -1:
usort($users, function($a, $b) {
return -($a->age <=> $b->age);
});
Conclusão
Dominar a ordenação de arrays de objetos em PHP é fundamental para qualquer desenvolvedor. Com usort(), uasort() e o operador spaceship, você tem ferramentas poderosas e flexíveis para organizar seus dados de forma eficiente. Pratique com diferentes tipos de propriedades e cenários para se tornar um expert no assunto!