Сортировка массива объектов по одному свойству в PHP: полный разбор

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Сортировка массива объектов в PHP: от новичка до профи

Представьте ситуацию: вы пишете интернет-магазин на PHP. У вас есть массив товаров, каждый товар — это объект с полями price, name, rating. Пользователь нажимает «Сортировать по цене», и вам нужно мгновенно перестроить этот массив. Как это сделать правильно и красиво? Именно об этом наш сегодняшний разбор.

Тема сортировки массива объектов по одному свойству в PHP — один из самых популярных запросов на Stack Overflow (миллионы просмотров!). И неудивительно: работа с объектами — основа современного PHP, а умение гибко сортировать данные — must-have навык. Давайте разберем все от простого к сложному, с живыми примерами и пояснениями.

Почему нельзя просто использовать sort()?

Новички часто пытаются применить sort() или rsort() к массиву объектов. И получают ошибку или полную бессмыслицу. Почему? Потому что эти функции сравнивают элементы как простые значения (числа или строки), а объект — это сложная структура. PHP не знает, по какому полю вы хотите сортировать: по имени, цене или дате. Нужно явно указать правило сравнения.

Именно для этого существуют функции usort(), uasort() и uksort(). Буква «u» в названии означает «user-defined» — пользовательская функция сравнения. Мы сами пишем, как сравнивать два объекта.

Базовый пример: сортируем пользователей по возрасту

Допустим, у нас есть класс User и массив пользователей:

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('Ольга', 22),
    new User('Петр', 28)
];

Нам нужно отсортировать их по возрастанию возраста. Используем usort:

usort($users, function($a, $b) {
    return $a->age <=> $b->age;
});

// Результат:
// Ольга (22), Анна (25), Петр (28), Иван (30)

Обратите внимание на spaceship operator ( <=> ) — он появился в PHP 7.0 и делает код невероятно лаконичным. Он возвращает -1, 0 или 1, что идеально подходит для функций сравнения.

Разбираем механизм работы usort

Функция usort() принимает два аргумента:

  • Массив (передается по ссылке — исходный массив изменится)
  • Callback-функцию, которая сравнивает два элемента

Callback должен вернуть:

  • Отрицательное число (обычно -1) — если первый элемент меньше второго
  • 0 — если элементы равны
  • Положительное число (обычно 1) — если первый элемент больше второго

Spaceship operator делает это автоматически. Вот как выглядит та же сортировка без него:

usort($users, function($a, $b) {
    if ($a->age == $b->age) return 0;
    return ($a->age < $b->age) ? -1 : 1;
});

Разница очевидна: оператор <=> сокращает 4 строки до одной. Используйте его везде, где поддерживается версия PHP 7+.

Сортировка по строкам: учитываем регистр и локаль

С числами всё просто, но строки требуют внимания. Давайте отсортируем тех же пользователей по имени:

usort($users, function($a, $b) {
    return strcmp($a->name, $b->name);
});

// Или с spaceship:
usort($users, function($a, $b) {
    return $a->name <=> $b->name;
});

Но есть нюанс: spaceship учитывает регистр. Строка «apple» будет меньше «Banana», потому что код символа 'a' (97) меньше 'B' (66). Для регистронезависимой сортировки используйте strcasecmp():

usort($users, function($a, $b) {
    return strcasecmp($a->name, $b->name);
});

А если у вас русские буквы и нужна сортировка по алфавиту с учетом локали — подключайте расширение intl и функцию Collator:

$collator = new Collator('ru_RU');
usort($users, function($a, $b) use ($collator) {
    return $collator->compare($a->name, $b->name);
});

Сортировка по убыванию: просто меняем порядок

Чтобы отсортировать по убыванию, достаточно поменять местами $a и $b:

// По убыванию возраста
usort($users, function($a, $b) {
    return $b->age <=> $a->age;
});

// Или просто умножьте результат на -1:
usort($users, function($a, $b) {
    return -($a->age <=> $b->age);
});

Сохраняем ключи: uasort vs usort

Важное различие: usort() сбрасывает числовые ключи массива (индексы становятся 0,1,2…). Если вам нужно сохранить ассоциативные ключи или исходные индексы, используйте uasort():

$products = [
    'id_5' => new Product('Ноутбук', 50000),
    'id_3' => new Product('Мышь', 1500),
    'id_8' => new Product('Клавиатура', 3000)
];

uasort($products, function($a, $b) {
    return $a->price <=> $b->price;
});

// Ключи 'id_5', 'id_3', 'id_8' сохранятся!

А uksort() сортирует по ключам массива, а не по значениям — тоже полезно.

Продвинутый уровень: сортировка по нескольким полям

Часто нужно сортировать по одному полю, а при равенстве — по другому. Например, сначала по рейтингу (по убыванию), затем по цене (по возрастанию):

usort($products, function($a, $b) {
    // Сначала сравниваем рейтинг (по убыванию)
    $ratingCompare = $b->rating <=> $a->rating;
    if ($ratingCompare !== 0) return $ratingCompare;
    
    // Если рейтинг равен, сравниваем цену (                

Блоги

Рекомендаций по книгам