Ordenação de array de objetos em PHP: do caos à ordem em 5 minutos
\n\nImagine: você está criando um site educacional em PHP e recebeu uma lista de estudantes do banco de dados. Cada estudante é um objeto com nome, idade e pontuação. Você precisa exibi-los na página: primeiro os mais velhos, ou, ao contrário, os mais novos. Ou, talvez, ordenar em ordem alfabética. Como fazer isso se você não tem um array simples de números, mas um array de objetos?
\n\nEsta pergunta é uma das mais populares no Stack Overflow. Milhares de desenvolvedores, de iniciantes a profissionais, enfrentam a tarefa de «sort array of objects by one property». E hoje vamos resolvê-la de uma vez por todas. Sem enrolação, com exemplos reais e explicações claras.
\n\nPor que o sort() comum não funciona?
\n\nSuponha que temos um array de objetos $students:
<?php\nclass Student {\n public $name;\n public $age;\n public $score;\n\n public function __construct($name, $age, $score) {\n $this->name = $name;\n $this->age = $age;\n $this->score = $score;\n }\n}\n\n$students = [\n new Student("Ana", 22, 85),\n new Student("João", 20, 92),\n new Student("Maria", 23, 78),\n new Student("Pedro", 21, 95)\n];\n?>\n\nSe você tentar chamar sort($students), o PHP emitirá um erro ou simplesmente não fará nada. Por quê? Porque sort() sabe comparar números e strings, mas não sabe como comparar dois objetos. É preciso explicar: «Compare pela propriedade age» ou «Compare por name». Para isso, o PHP tem uma função especial — usort().
Conheça: usort() — sua principal ferramenta
\n\nA função usort() recebe dois argumentos: o próprio array e uma função de comparação. Esta função de comparação deve retornar:
- \n
- 0, se os elementos forem iguais; \n
- número negativo, se o primeiro elemento for menor que o segundo; \n
- número positivo, se o primeiro elemento for maior que o segundo. \n
Parece complicado? Na prática, é simples. Vamos ordenar os estudantes por idade (em ordem crescente):
\n\n<?php\nusort($students, function($a, $b) {\n return $a->age <=> $b->age;\n});\n\n// Resultado: João (20), Pedro (21), Ana (22), Maria (23)\n?>\n\nObserve o operador <=> (nave espacial). Ele surgiu no PHP 7 e torna a ordenação extremamente concisa. Ele compara dois valores e retorna -1, 0 ou 1. Exatamente o que o usort() precisa.
Ordenação decrescente: invertendo o sinal
\n\nQuer ordenar do mais velho para o mais novo? Basta inverter os operandos no operador <=>:
\n\n<?php\nusort($students, function($a, $b) {\n return $b->age <=> $a->age; // agora b é comparado com a\n});\n\n// Resultado: Maria (23), Ana (22), Pedro (21), João (20)\n?>\n\nOu, de forma equivalente, multiplique o resultado por -1:
\n\n<?php\nusort($students, function($a, $b) {\n return -($a->age <=> $b->age);\n});\n?>\n\nOrdenação por strings (ordem alfabética)
\n\nE se a propriedade for uma string? Por exemplo, o nome. O mesmo princípio, mas em vez de <=>, usamos strcmp() ou strcasecmp() (para comparação sem distinção de maiúsculas/minúsculas):
<?php\n// Em ordem alfabética (A-Z)\nusort($students, function($a, $b) {\n return strcmp($a->name, $b->name);\n});\n\n// Resultado: Ana, João, Maria, Pedro\n\n// Em ordem alfabética inversa (Z-A)\nusort($students, function($a, $b) {\n return strcmp($b->name, $a->name);\n});\n?>\n\nOrdenação por propriedade numérica: alternativa ao <=>
\n\nO operador <=> é conveniente, mas se você estiver trabalhando com PHP antigo (anterior ao 7.0), ele não existe. Nesse caso, escrevemos a comparação manualmente: