Який в тебе масив — асоціативний чи індексований?

← Який в тебе масив — асоціативний чи індексований?

Ashterix

docs: English JsonRpcBundle docs, REST and MCP Bundle sections, package cards

uk/articles/from-tg/php/php-arrays.md новий файл +70 −0

Який в тебе масив — асоціативний чи індексований?

В PHP масив — це універсальний інструмент, який не вимагає від тебе визначати розмір, тип елементів чи навіть структуру ключів. Це з одного боку ніби і зручно, але з іншого — є проблемою.

Більшість мов програмування виділяють масиви (indexed arrays) і словники/мапи (associative arrays), а в PHP це одна й та ж сама структура: будь-який масив може стати асоціативним або нумерованим в залежності від ключів, які ти використовуєш:

$a = [1, 2, 3, 4, 5];  // індексований
$b = ['foo' => 6];     // асоціативний
$c = [
    ...$a,
    ...$b
];                     // змішаний

Часто виникає потреба по-різному обробляти масиви в залежності від їх типу. Але PHP не дає такої базової можливості, бо він взагалі не розрізняє індексовані та асоціативні масиви, про що прямо написано в документації.

Чи допоможе array_is_list?

Можна подумати, що array_is_list може допомогти зʼясувати, хто є хто:

array_is_list($a); // true  [0=>1, 1=>2, 2=>3, 3=>4, 4=>5]
array_is_list($b); // false [foo=>6]
array_is_list($c); // false [0=>1, 1=>2, 2=>3, 3=>4, 4=>5, foo=>6]

На перший погляд все добре, але ні.

Розширимо наш приклад: витягнемо з масиву $a тільки непарні числа.

$a2 = array_filter($a, fn($x) => $x % 2 !== 0); // 1,3,5
array_is_list($a2); // false бо 0=>1, 2=>3, 4=>5

Що сталося з масивом? Невже він став асоціативним?

Ні. Просто array_filter зберігає оригінальні ключі. І хоч це все ще числові ключі, але через “дірки” в індексації array_is_list повертає false.

Тобто PHP не ставить знак дорівнює між "нумерованим" та "індексованим" типами масивів.

Рядкові ключі — не гарантують “асоціативність”

Ще одна неприємність, яка може вас очікувати.

Багато хто вважає, що якщо в масиві ключ рядковий — все, це асоціативний масив. Але якщо ключ виглядає як число, PHP конвертує його в int. Наприклад, штрихкоди товарів:

$products = [
    "0123456789052" => "Товар",
    "8018075001428" => "Ще товар"
];
print_r(array_keys($products));
//Array
//(
//    [0] => "0123456789052" 
//    [1] => 8018075001428 // -- рядок став числом
//)

Тому на ключі типу “рядок чи число” теж покладатися не можна.

Висновок

Я бачив багато коду, де масив використовують як list, а потім раптово додають рядковий ключ — і все, data integrity накрилась. Якщо твоя логіка дійсно залежить від того, який у тебе масив — перевіряй не array_is_list, а реально структуру ключів (через array_keys, is_int, is_string і т.д.). А ще краще — не лінуйся типізувати і перевіряти дані на вході, навіть якщо це PHP.


Вперше опубліковано в Telegram-каналі «Створений щоб помирати» 17.07.2025.