Is your array associative or indexed?

Is your array associative or indexed?

In PHP, an array is a universal tool that doesn't require you to define its size, the type of its elements or even the structure of its keys. On the one hand that's convenient, but on the other — it's a problem.

Most programming languages distinguish between arrays (indexed arrays) and dictionaries/maps (associative arrays), but in PHP it's one and the same structure: any array can become associative or numbered depending on the keys you use:

$a = [1, 2, 3, 4, 5];  // indexed
$b = ['foo' => 6];     // associative
$c = [
    ...$a,
    ...$b
];                     // mixed

You often need to handle arrays differently depending on their type. But PHP doesn't give you such a basic ability, because it doesn't distinguish between indexed and associative arrays at all, as the documentation says explicitly.

Will array_is_list help?

You might think that array_is_list can help figure out which is which:

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]

At first glance everything is fine, but no.

Let's extend our example: take only the odd numbers from the $a array.

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

What happened to the array? Did it become associative?

No. It's just that array_filter preserves the original keys. And although they are still numeric keys, because of the "holes" in the indexing array_is_list returns false.

In other words, PHP doesn't put an equals sign between "numbered" and "indexed" arrays.

String keys don't guarantee "associativity"

One more unpleasant surprise that may be waiting for you.

Many people believe that if an array has a string key, that's it, it's an associative array. But if the key looks like a number, PHP converts it to int. For example, product barcodes:

$products = [
    "0123456789052" => "Product",
    "8018075001428" => "Another product"
];
print_r(array_keys($products));
//Array
//(
//    [0] => "0123456789052" 
//    [1] => 8018075001428 // -- the string became a number
//)

So you can't rely on keys being "string or number" either.

Conclusion

I've seen a lot of code where an array is used as a list, and then suddenly a string key is added — and that's it, data integrity is gone. If your logic really depends on what kind of array you have, check the actual key structure (via array_keys, is_int, is_string etc.) rather than array_is_list. And even better — don't be lazy: type and validate your input data, even if it's PHP.


First published in Ukrainian in the Telegram channel “Created to die” on July 17, 2025.