Сортировка многомерного массива в PHP.
Пояснение к задачке "Список стран".
Итак, имеется довольно простая учебная задача, отобразить на странице список стран с флагами, кодами ISO и наименованиями на английском и русском, необходимо обеспечить сортировку по столбцам базы данных (таблицы). В качестве хранилища данных выбираем текстовый файл формата
CSV с разделителями "точка с запятой" (;). Готовый файл можно взять здесь или здесь. Для отображения флагов, понадобятся соответствующие картинки. Можно взять здесь или здесьДля выбора поля, по которому сортировать данные, а также, как их сортировать (по возрастанию или убыванию), необходима форма. Добавляем код, генерирующий форму в функцию
print_sortform(), которая будет вызываться после функции print_top(), которая, в свою очередь, печатает заголовок HTML и заголовок таблицы.( Код функции )
Ранее в скрипте объявляем две глобальных переменных
$field = "ISOA2"; //поле, по которому будем сортировать
$direction = 0; //направление сортировки: 0 - по возрастанию,
//иначе - по убыванию
и два массива в самой функции -
$fields и $sortmess, содержащие идентификаторы полей и информацию для отображения их в форме. Далее в цикле foreach формируем набор из переключателей (radiobutton) для выбора нужного поля. Остальное в функции достаточно тривиально.
Данные будем хранить в многомерном массиве вот такой структуры:

Функция загрузки:
( Загрузка данных )
Заводим глобальную переменную
$errmsg для того, чтоб туда писать сообщение об ошибке, и глобальный массив $data для нашей таблицы (БД), да, очевидный минус - я не стал париться с количеством элементов разбитой в массив строки. Но для PHP это не так, чтобы и критично. Если что просто вывалится с ошибкой. Некоторые вообще не заморачиваются обработкой ошибок в PHP, а отдают все на волю интерпретатора. Далее, читаем построчно, разбиваем строку на составляющие и дописываем в массив ассоциативный массив с указанными полями, соответственно, в каждом элементе массива
$data будет ассоциативный массив с данными, по одному на строку. В итоге получится многомерный (вложенный) массив (в терминах PHP, в других языках "многомерный" может означать несколько другое, по мне бы так термин "вложенный" был бы лучше).Передаем их в
GET-параметрах. Значения параметров пишем в глобальные переменные.if (isset($_GET['sort']))
{
$field=$_GET['sort'];
}
if (isset($_GET['direction']))
{
$direction=$_GET['direction'];
}Проверять корректность переданных значений будем в функции сортировки.
В PHP имеется функция сортировки
usort(); которая принимает массив данных, в качестве первого параметра, и функцию сортировки в качестве второго. Функцию сортировки описывает пользователь. В нее передается два элемента массива, а пользователь описывает алгоритм сравнения, таким образом, чтобы пользовательская функция выдавала 3 значения: -1: 1-й элемент < 2-го элемента, 0: 1-й элемент == 2-му элементу, 1: 1-й элемент > 2-го элемента. Пишем соответствующую пользовательскую функцию:function compare ($a, $b)
{
global $field;
global $direction;
global $errmsg;
if (!array_key_exists($field, $a))
{
$errmsg = "Field $field not found";
return 0;
}
if ($direction == 0)
{
return strnatcmp($a[$field],$b[$field]);
}
else
{
return (strnatcmp($a[$field],$b[$field])*-1);
}
}1. В переменные
$a и $b передаются два элемента массива, который надо отсортировать.2. Далее, подключаемся к ранее заданным глобальным переменным:
$field - поле таблицы (БД), по которому будем сортировать.$direction - направление сортировки - 0 по возрастанию, другое значение - по убыванию.3. Проверяем, есть ли соответствующий ключ в массиве, а это надо проверить, т.к. ключ передается в запросе, а в запросе может придти не то, что ожидает скрипт.
if (!array_key_exists($field, $a))
...4. Проверяем, как сортировать и сортируем с помощью функции
strnatcmp(). От стандартной strcmp() она отличается тем, что если ей попадается набор чисел в виде строк, то она их будет сортировать в формате, обычном для человека:strnatcmp():4
8
10
12
16
20
24
28strcmp():
10
100
104
108
112
116
12
120
124strnatcpm() (и strcpm()), как раз возвразащают 0, если аргументы равны, -1 если 1-й > 2-го, и 1, если 2-й > 1-го.Чтобы поменять порядок сортировки на обратный, достаточно поменять результат работы функции на обратный, что можно сделать, умножив результат функции
strnatcmp()/strcmp() на -1:(strnatcmp($a[$field],$b[$field])*-1)Скриншот:

Исходник
Посмотреть, как работает
- Нет флагов некоторых редких стран (может быть потом сам нарисую).
- Почему-то страны на русскую букву
Р криво сортируются, если сортировать по русским наименованиям стран.usort()Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2020/09/15/sort