В PHP есть только один тип данных для массивов — Array. Его уникальность состоит в том, что с одной стороны он работает как обычный массив, а с другой — как ассоциативный. Зависит от того, как его используют.
Поначалу такой подход может подкупить своей кажущейся простотой, особенно тех, кто не имел дела с другими языками. Но чем дальше в код, тем больше проблем он приносит.
Самый простой пример — JSON. В JSON массив и ассоциативный массив — разные сущности:
Ассоциативный массив
{
"key": "value",
"key2": "value2"
}
Массив
["value", "value2"]
Если преобразовать JSON в структуру на PHP, то эта информация теряется:
<?php
// Это JSON, в котором есть и массив, и ассоциативный массив
$json = '{ "key": "value", "key2": [1, 2] }';
json_decode($json, true);
// Внутри PHP разницы нет, так как все массивы ассоциативные
// Array
// (
// [key] => value
// [key2] => Array
// (
// [0] => 1
// [1] => 2
// )
// )
Если мы не знаем структуру JSON, то у нас нет простого способа понять, что перед нами — массив или ассоциативный массив. В интернете с подобным сталкиваются постоянно и предлагают такой способ, как анализ ключей. Если они все числовые, то считаем, что массив, иначе — ассоциативный массив.
<?php
function isAssoc(array $items)
{
if ($items === []) return false;
return array_keys($items) !== range(0, count($items) - 1);
}
isAssoc(['a', 'b', 'c']); // false
isAssoc(['1' => 'a', '0' => 'b', '2' => 'c']); // true
Конвертация из массива в JSON сопряжена с такими же проблемами. Как понять, во что конвертировать переданный массив?
Другая проблема заключается в том, что достаточно легко ошибиться с типом массива и начать его использовать не по назначению:
<?php
$data = [];
$data[] = 10;
$data['key'] = 'value';
$data[] = 'hi!';
Первое удивление — код работает! Теперь попробуйте догадаться, что находится внутри $data
.
<?php
print_r($data);
// => Array
// (
// [0] => 10
// [key] => value
// [1] => hi!
// )
Из этого вывода должно быть понятно, что индексированных массивов в PHP нет. Есть упорядоченные ассоциативные массивы, с операцией [] =
: добавить элемент с автоматическим присвоением ключа.
<?php
$data = ['key' => 'value'];
$data[] = 'console';
// Array
// (
// [key] => value
// [0] => console
// )
Но самое неудобное — функции которые могут сохранять, а могут не сохранять ключи. Обычно в таких функциях есть дополнительный параметр флаг preserve_keys
, который меняет описанное поведение.
array_reverse
array_reverse(array $array, bool $preserve_keys = false): array
Если preserve_keys установлен в TRUE, то числовые ключи будут сохранены. Нечисловые ключи не подвержены этой опции и всегда сохраняются.
array_unique
array_unique(array $array, int $flags = SORT_STRING): array
Обратите внимание, что ключи сохранятся. Если в соответствии с заданными flags несколько элементов определяются как идентичные, то будут сохранены ключ и значение первого такого элемента.
По сути, в описании каждой функции, которая принимает на вход массив (или массивы) и возвращает массив, есть секция с пояснением, сохраняет ли ключи функция или нет, и как это поведение можно изменить.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.