My love-hate relationship with PHP: Arrays
I’ve been programming PHP for most of my life, almost 20 years now. While PHP has many downsides, horrible history, and terrible reputation, it has improved a lot with PHP 7 and modern frameworks like Laravel that make it really enjoyable to develop.
However, I still wish that there would be a “PHP2", a rework of the original one boldly breaking the backward compatibility and fixing some of the underlying weirdness.
Array is an array
Since PHP 5.4, you’ve been able to create PHP arrays with a shorthand developers from other languages are able to understand immediately. It will create an array with values defined between [ and ] and when you encode it to JSON for passing through an API, you get a JSON array. Wonderful. (I started developing with PHP 4 so that was a very welcome improvement)
You can do all the basic array operations for these arrays: sorting, popping, mapping, reducing, etc. Life is good.
Array is an object
You can also create key-value stores with the fat arrow notation. Using the same shorthand, you define a key and a value and life is good. You can sort the new array either by value or key, you can loop over it with foreach and so on. All the goodies you’re used to with maps, objects or dictionaries in other languages.
Array becomes an object
The trick here is that actually, all arrays in PHP are key-value stores. So when you initialize an array with
[1, 2, 3, 4, 5], you actually create a key-value store of
[0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5]. So when you use json_encode to do the encoding, it will return a JSON array if and only if:
- The keys of the array are 0 to n, AND
- The keys are in order from 0 to n
otherwise it will return a JSON object. So running operations to modify your array can cause the keys to mess up and you end up getting something you didn’t expect.
Array sometimes becomes an array and sometimes an object
The scary part of PHP, and a cause of a lot of bugs, is when you can run certain array operations to different arrays with similar structure and the type of the JSON encoded is different.
If you sort an array with numeric, sequential and unordered keys, you turn from object to an array. If you sort an array with numeric, sequential and ordered keys, it remains an array. Whatever you do for non-numeric or non-sequential array, it will stay an object.
I think that whenever a normal operation run on a dynamic data and the type of the end result (well, technically the return type of json_encode is always string but you know what I mean) is sometimes different, we’re in very murky waters.
Having different types for sequential arrays (like
[1, 2, 3, 4] and associative arrays
[ 0 => 1, 1 => 2, 2 => 3]) is definitely on my wishlist for Santa this year.