Сортировка массива по значению колонки в PHP: полный гайд

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

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

Начать курс

Почему сортировка ассоциативных массивов — это боль (и как её вылечить)

Представьте: вы вытянули из базы данных список пользователей. У каждого — имя, возраст, город, рейтинг. Данные пришли в виде массива ассоциативных массивов. И тут босс говорит: «Отсортируй по возрасту, а потом ещё по рейтингу в обратном порядке». Знакомая ситуация? Если вы хоть раз писали на PHP, то наверняка сталкивались с задачей: sort an array of associative arrays by column value. Вопрос с тысячами просмотров на Stack Overflow не врёт — это реальный камень преткновения для многих разработчиков.

В этой статье мы разберём все способы сортировки многомерных массивов в PHP. От простого usort до мощного array_multisort. Вы узнаете, как сортировать по одному полю, по нескольким полям, в разных направлениях и как не наступить на грабли с типами данных. Поехали!

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

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

<?php
$users = [
    ['name' => 'Анна', 'age' => 25, 'rating' => 4.7],
    ['name' => 'Иван', 'age' => 30, 'rating' => 3.9],
    ['name' => 'Мария', 'age' => 22, 'rating' => 4.9],
];
?>

Если попробовать sort($users), PHP выдаст предупреждение и оставит массив нетронутым. Почему? Потому что sort() сравнивает элементы напрямую, а PHP не знает, как сравнивать ассоциативные массивы. Ему нужна подсказка — какое поле считать критерием сортировки.

Способ №1: usort() — король кастомной сортировки

Функция usort() принимает массив и callback-функцию, которая сравнивает два элемента. Это самый гибкий и часто используемый способ.

Сортировка по одному полю (по возрастанию)

<?php
usort($users, function($a, $b) {
    return $a['age'] <=> $b['age'];
});
// Результат: Мария (22), Анна (25), Иван (30)
?>

Оператор <=> (космический корабль) появился в PHP 7 и делает код чище. Он возвращает -1, 0 или 1 в зависимости от сравнения. Если нужно по убыванию — просто поменяйте местами $a и $b:

<?php
usort($users, function($a, $b) {
    return $b['age'] <=> $a['age'];
});
// Результат: Иван (30), Анна (25), Мария (22)
?>

Сортировка по строковому полю

Со строками всё работает так же, но важно помнить про локаль. Если вы сортируете русские имена, используйте setlocale() и strcoll() для корректной обработки кириллицы:

<?php
setlocale(LC_ALL, 'ru_RU.UTF-8');
usort($users, function($a, $b) {
    return strcoll($a['name'], $b['name']);
});
?>

Способ №2: array_multisort() — для сортировки по нескольким колонкам

Когда нужно отсортировать сначала по одному полю, а потом по другому (например, по городу, а внутри города — по возрасту), usort начинает требовать сложной логики. Тут на помощь приходит array_multisort().

Сортировка по двум полям

<?php
$ages = array_column($users, 'age');
$ratings = array_column($users, 'rating');
array_multisort($ages, SORT_ASC, $ratings, SORT_DESC, $users);
?>

Разберём магию: мы создаём отдельные массивы из нужных колонок, а затем передаём их в array_multisort. Важно: исходный массив передаётся последним — он будет пересортирован в соответствии с порядком первых массивов. Это мощный, но опасный инструмент: если колонки разной длины, получите ошибку.

Способ №3: array_column() + sort() — хак для однострочников

Если вам нужно просто отсортировать массив по одному числовому полю, можно использовать комбинацию array_column() и array_multisort() в одну строку:

<?php
array_multisort(array_column($users, 'age'), SORT_ASC, $users);
?>

Этот приём особенно популярен на Stack Overflow, потому что он короткий и не требует написания callback-функции. Но помните: он не подходит для сложных сравнений строк или сортировки с учётом локали.

Способ №4: sort() с флагом SORT_FLAG_CASE — для одномерных массивов

Этот способ не совсем про нашу тему, но часто встречается рядом. Если у вас одномерный массив строк и нужно отсортировать без учёта регистра:

<?php
$fruits = ['Apple', 'banana', 'Cherry'];
sort($fruits, SORT_STRING | SORT_FLAG_CASE);
// Результат: Apple, banana, Cherry (регистронезависимая сортировка)
?>

Для ассоциативных массивов это не работает напрямую, но можно комбинировать с array_column().

Способ №5: Использование array_multisort() с разными направлениями

Допустим, нужно отсортировать пользователей по рейтингу (по убыванию), а при равном рейтинге — по возрасту (по возрастанию).

<?php
$ratings = array_column($users, 'rating');
$ages = array_column($users, 'age');
array_multisort(
    $ratings, SORT_DESC,
    $ages, SORT_ASC,
    $users
);
?>

Обратите внимание: флаги направления (SORT_ASC, SORT_DESC) применяются к соответствующему массиву. Если не указать флаг, по умолчанию используется SORT_ASC.

Частые ошибки и как их избежать

Ошибка 1: Смешивание типов данных

Если в колонке age у вас есть строка '25' и число 25, сортировка может дать неожиданный результат. PHP будет сравнивать их как строки или числа в зависимости от контекста. Решение: всегда приводите типы перед сортировкой.

<?php
$users = array_map(function($user) {
    $user['age'] = (int)$user['age'];
    return $user;
}, $users);
?>

Ошибка 2: Потеря ключей при usort()

usort()

Блоги

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