Сортировка многомерного массива в PHP

Александр Кичатов

Сортировка многомерного массива по значению поля

Представим, что у нас есть многомерный массив с товарами:

$products = [
    ['id' => 1, 'name' => 'Товар 1', 'price' => 1000],
    ['id' => 2, 'name' => 'Товар 2', 'price' => 500],
    ['id' => 3, 'name' => 'Товар 3', 'price' => 2000],
    ['id' => 4, 'name' => 'Товар 4', 'price' => 300]
];

И нужно отсортировать этот массив по цене. Как это сделать?

Для этого в PHP существует специальная функция usort(). Вот готовый пример:

function mySort($a, $b) {
    if($a['price'] == $b['price'])
        return 0;

    if($a['price'] < $b['price'])
        return -1;
    else
        return 1;
}

usort($products, 'mySort');

print_r($products);

Как работает функция usort()

Поскольку PHP не знает, по каким критериям нужно сортировать массив, мы описываем эти критерии в отдельной функции под названием mySort() (название может быть любым).

Задача этой функции простая - она должна принять два случайных элемента массива ($a и $b), сравнить их и вернуть одно из трёх значений:

  • 0 если $a и $b равны
  • -1 если $a меньше $b
  • 1 если $a больше $b

Именно это мы сделали в примере выше.

Сокращение кода

Разумеется, if-else можно заменить на тернарный оператор:

function mySort($a, $b) {
    if($a['price'] == $b['price'])
        return 0;

    return $a['price'] < $b['price'] ? -1 : 1;
}

usort($products, 'mySort');

Поскольку вторым параметром usort принимает callable, не обязательно создавать отдельную функцию сортировки, можно передать безымянную функцию:

usort($products, function ($a, $b) {
    if($a['price'] == $b['price'])
        return 0;

    return $a['price'] < $b['price'] ? -1 : 1;
});

Кроме этого, в PHP 7 появился оператор spaceship (летающий корабль) <=>. Он возвращает -1, 0 или 1 если $a меньше, равна или больше $b. С этим оператором код становится гораздо короче:

usort($products, function ($a, $b) {
    return $a['price'] <=> $b['price'];
});

Несколько условий сортировки

Разумеется, в функции сортировки можно указать сколько угодно правил:

usort($products, function ($a, $b) {

    // Сначала сравниваем по цене
    if($a['price'] != $b['price'])
        return $a > $b ? 1 : -1;

    // Если цены равны, сравниваем по id
    return $a['id'] <=> $b['id'];
});

Сортировка массива, полученного из БД

Если массив с данными получен из базы данных, лучше сначала подумать, нет ли способа отсортировать данные ещё до их получения, в самом SQL-запросе.

За сортировку в SQL отвечает команда ORDER BY. Сортировка по возрастанию выглядит так:

SELECT * FROM `products` ORDER BY `id`

По убыванию:

SELECT * FROM `products` ORDER BY `id` DESC

Сортируем сначала по наличию товара на складе, затем по возрастанию цены:

SELECT * FROM `products` ORDER BY `in_stock` DESC, `price`

Сначала выведем товар с id=15, затем товары с ценой больше 5000:

SELECT * FROM `products` ORDER BY `id` = 15 DESC, `price` > 5000 DESC

Комментарии