Как отсортировать массив объектов по одному свойству в PHP?
Решение: используем usort() с пользовательской функцией сравнения
Для сортировки массива объектов в PHP лучше всего подходит функция usort(). Она принимает два аргумента: сам массив (передаётся по ссылке) и callback-функцию, которая сравнивает два элемента и возвращает целое число:
- 0 — если элементы равны
- Отрицательное число — если первый элемент должен идти перед вторым
- Положительное число — если первый элемент должен идти после второго
Вот как это работает для вашего примера с сортировкой по возрасту:
usort($users, function($a, $b) {
return $a->age - $b->age;
});
Принцип простой: если $a->age меньше $b->age, разность будет отрицательной — значит, $a встанет перед $b. Если больше — положительной, и $a встанет после. Если равны — 0, порядок не меняется.
Полный рабочий пример:
class User {
public $name;
public $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
}
$users = [
new User('Иван', 25),
new User('Мария', 30),
new User('Петр', 20),
new User('Анна', 28)
];
// Сортировка по возрасту (возрастание)
usort($users, function($a, $b) {
return $a->age - $b->age;
});
foreach ($users as $user) {
echo $user->name . ' (' . $user->age . ')<br>';
}
// Результат:
// Петр (20)
// Иван (25)
// Анна (28)
// Мария (30)
Сортировка по убыванию
Чтобы отсортировать по убыванию, просто поменяйте операнды местами:
usort($users, function($a, $b) {
return $b->age - $a->age;
});
Сортировка по строковому свойству (например, по имени)
Для строк используйте функцию strcmp() или оператор spaceship (<=>), доступный с PHP 7:
// Вариант 1: с strcmp()
usort($users, function($a, $b) {
return strcmp($a->name, $b->name);
});
// Вариант 2: с оператором spaceship (PHP 7+)
usort($users, function($a, $b) {
return $a->name <=> $b->name;
});
Результат сортировки по имени: Анна, Иван, Мария, Петр (в алфавитном порядке).
Сортировка по нескольким свойствам
Если нужно отсортировать сначала по возрасту, а при равенстве — по имени:
usort($users, function($a, $b) {
$ageCompare = $a->age - $b->age;
if ($ageCompare === 0) {
return strcmp($a->name, $b->name);
}
return $ageCompare;
});
Важные замечания
usort()изменяет исходный массив (передаётся по ссылке). Если нужно сохранить оригинал, скопируйте массив через$sorted = $users;перед сортировкой.- Для сортировки ассоциативных массивов по значению ключа используйте
usort()аналогичным образом, обращаясь к элементам как к массиву:$a['age'] - $b['age']. - Начиная с PHP 7.4 можно использовать стрелочные функции для краткости:
usort($users, fn($a, $b) => $a->age - $b->age);
Альтернативный подход: создание вспомогательного массива
Если вам неудобно писать callback-функции, можно использовать старый добрый метод с созданием временного массива для сортировки. Он менее элегантный, но наглядный для новичков:
$ages = [];
foreach ($users as $key => $user) {
$ages[$key] = $user->age;
}
// Сортируем массив возрастов, сохраняя ключи
array_multisort($ages, SORT_ASC, $users);
// Теперь $users отсортирован по возрасту
Этот метод особенно удобен, когда нужно отсортировать несколько связанных массивов одновременно. array_multisort() может принимать несколько массивов и сортировать их синхронно.
Минусы подхода: больше кода, создаётся дополнительный массив в памяти. Для больших массивов (сотни тысяч элементов) это может быть менее эффективно, чем usort().
Также можно использовать array_column() для извлечения значений свойств (работает с PHP 5.5+):
$ages = array_column($users, 'age');
array_multisort($ages, SORT_ASC, $users);
Этот вариант короче, но требует, чтобы свойства объектов были публичными (как в вашем примере).