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

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

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

Начать курс

Сортировка массива объектов в PHP: от хаоса к порядку за 5 минут

Представьте: вы пишете образовательный сайт на PHP и получили список студентов из базы данных. Каждый студент — это объект с именем, возрастом и баллами. Вам нужно вывести их на страницу: сначала самых старших, или, наоборот, самых младших. Или, может быть, отсортировать по алфавиту. Как это сделать, если у вас не простой массив чисел, а массив объектов?

Этот вопрос — один из самых популярных на Stack Overflow. Тысячи разработчиков, от новичков до профи, сталкиваются с задачей «sort array of objects by one property». И сегодня мы разберём её раз и навсегда. Без воды, с живыми примерами и понятными объяснениями.

Почему обычная sort() не работает?

Допустим, у нас есть массив объектов $students:

<?php
class Student {
    public $name;
    public $age;
    public $score;

    public function __construct($name, $age, $score) {
        $this->name = $name;
        $this->age = $age;
        $this->score = $score;
    }
}

$students = [
    new Student("Анна", 22, 85),
    new Student("Иван", 20, 92),
    new Student("Мария", 23, 78),
    new Student("Пётр", 21, 95)
];
?>

Если вы попробуете вызвать sort($students), PHP выдаст ошибку или просто ничего не сделает. Почему? Потому что sort() умеет сравнивать числа и строки, но не знает, как сравнивать два объекта. Ей нужно объяснить: «Сравнивай по свойству age» или «Сравнивай по name». Для этого в PHP есть специальная функция — usort().

Знакомьтесь: usort() — ваш главный инструмент

Функция usort() принимает два аргумента: сам массив и функцию сравнения. Эта функция сравнения должна вернуть:

  • 0, если элементы равны;
  • отрицательное число, если первый элемент меньше второго;
  • положительное число, если первый элемент больше второго.

Звучит сложно? На деле это просто. Давайте отсортируем студентов по возрасту (по возрастанию):

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

// Результат: Иван (20), Пётр (21), Анна (22), Мария (23)
?>

Обратите внимание на оператор <=> (космический корабль). Он появился в PHP 7 и делает сортировку максимально лаконичной. Он сравнивает два значения и возвращает -1, 0 или 1. Именно то, что нужно usort().

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

Хотите отсортировать от старшего к младшему? Просто поменяйте местами операнды в операторе <=>:

<?php
usort($students, function($a, $b) {
    return $b->age <=> $a->age;  // теперь b сравнивается с a
});

// Результат: Мария (23), Анна (22), Пётр (21), Иван (20)
?>

Или, что то же самое, умножьте результат на -1:

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

Сортировка по строкам (алфавиту)

А если свойство — строка? Например, имя. Тот же принцип, но вместо <=> используем strcmp() или strcasecmp() (для регистронезависимого сравнения):

<?php
// По алфавиту (А-Я)
usort($students, function($a, $b) {
    return strcmp($a->name, $b->name);
});

// Результат: Анна, Иван, Мария, Пётр

// По алфавиту (Я-А) — обратный порядок
usort($students, function($a, $b) {
    return strcmp($b->name, $a->name);
});
?>

Сортировка по числовому свойству: альтернатива <=>

Оператор <=> удобен, но если вы работаете со старым PHP (до 7.0), его нет. Тогда пишем сравнение вручную:

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

// Результат: Мария (78), Анна (85), Иван (92), Пётр (95)
?>

Этот код делает то же самое, что и <=>, но более громоздко. Используйте его только если застряли на PHP 5.

Реальный кейс: сортировка по дате

Часто объекты содержат даты в виде строк (например, "2024-03-15"). Простое строковое сравнение strcmp тут не подойдёт — даты в формате "Y-m-d" можно сравнивать как строки, но если формат другой? Лучше преобразовать в timestamp:

<?php
class Event {
    public $title;
    public $date; // строка вида "2024-03-15"

    public function __construct($title, $date) {
        $this->title = $title;
        $this->date = $date;
    }
}

$events = [
    new Event("Конференция PHP", "2024-06-10"),
    new Event("Хакатон", "2024-03-15"),
    new Event("Воркшоп", "2024-09-01")
];

usort($events, function($a, $b) {
    return strtotime($a->date) <=> strtotime($b->date);
});

// Результат: Хакатон (15.03), Конференция (10.06), Воркшоп (01.09)
?>

Сортировка по нескольким свойствам

Бывает нужно отсортировать сначала по одному полю, а потом по другому (например, по возрасту, а при равном возрасте — по имени). Решение — вложенные условия:

<?php
usort($students, function($a, $b) {
    // Сначала по возрасту
    $ageCompare = $a->age <=> $b->age;
    if ($ageCompare !== 0) {
        return $ageCompare;
    }
    // Если возраст одинаковый — по имени
    return strcmp($a->name, $b->name);
});
?>

Частая ошибка нович

Блоги

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