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

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

Ashterix

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

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

1 + # Який в тебе масив — асоціативний чи індексований?
2 +
3 + В PHP масив — це універсальний інструмент, який не вимагає від тебе визначати розмір, тип елементів чи навіть структуру ключів. Це з одного боку ніби і зручно, але з іншого — є проблемою.
4 +
5 + Більшість мов програмування виділяють масиви (indexed arrays) і словники/мапи (associative arrays), а в PHP це одна й та ж сама структура: будь-який масив може стати асоціативним або нумерованим в залежності від ключів, які ти використовуєш:
6 +
7 + ```php
8 + $a = [1, 2, 3, 4, 5]; // індексований
9 + $b = ['foo' => 6]; // асоціативний
10 + $c = [
11 + ...$a,
12 + ...$b
13 + ]; // змішаний
14 + ```
15 +
16 + Часто виникає потреба по-різному обробляти масиви в залежності від їх типу. Але PHP не дає такої базової можливості, бо він взагалі не розрізняє індексовані та асоціативні масиви, про що прямо написано в [документації](https://www.php.net/manual/uk/language.types.array.php).
17 +
18 + ## Чи допоможе array_is_list?
19 +
20 + Можна подумати, що `array_is_list` може допомогти зʼясувати, хто є хто:
21 +
22 + ```php
23 + array_is_list($a); // true [0=>1, 1=>2, 2=>3, 3=>4, 4=>5]
24 + array_is_list($b); // false [foo=>6]
25 + array_is_list($c); // false [0=>1, 1=>2, 2=>3, 3=>4, 4=>5, foo=>6]
26 + ```
27 +
28 + На перший погляд все добре, але ні.
29 +
30 + Розширимо наш приклад: витягнемо з масиву `$a` тільки непарні числа.
31 +
32 + ```php
33 + $a2 = array_filter($a, fn($x) => $x % 2 !== 0); // 1,3,5
34 + array_is_list($a2); // false бо 0=>1, 2=>3, 4=>5
35 + ```
36 +
37 + ### Що сталося з масивом? Невже він став асоціативним?
38 +
39 + Ні. Просто `array_filter` зберігає оригінальні ключі. І хоч це все ще числові ключі, але через “дірки” в індексації `array_is_list` повертає `false`.
40 +
41 + Тобто PHP не ставить знак дорівнює між "нумерованим" та "індексованим" типами масивів.
42 +
43 + ## Рядкові ключі — не гарантують “асоціативність”
44 +
45 + Ще одна неприємність, яка може вас очікувати.
46 +
47 + Багато хто вважає, що якщо в масиві ключ рядковий — все, це асоціативний масив. Але якщо ключ виглядає як число, PHP конвертує його в **int**. Наприклад, штрихкоди товарів:
48 +
49 + ```php
50 + $products = [
51 + "0123456789052" => "Товар",
52 + "8018075001428" => "Ще товар"
53 + ];
54 + print_r(array_keys($products));
55 + //Array
56 + //(
57 + // [0] => "0123456789052"
58 + // [1] => 8018075001428 // -- рядок став числом
59 + //)
60 + ```
61 +
62 + Тому на ключі типу “рядок чи число” теж покладатися не можна.
63 +
64 + ## Висновок
65 +
66 + > Я бачив багато коду, де масив використовують як list, а потім раптово додають рядковий ключ — і все, data integrity накрилась. Якщо твоя логіка дійсно залежить від того, який у тебе масив — перевіряй не `array_is_list`, а реально структуру ключів (через `array_keys`, `is_int`, `is_string` і т.д.). А ще краще — не лінуйся типізувати і перевіряти дані на вході, навіть якщо це PHP.
67 +
68 + ---
69 +
70 + *Вперше опубліковано в Telegram-каналі [«Створений щоб помирати»](https://t.me/php_while_true/57) 17.07.2025.*