PHP Gotcha: Strings are Arrays Too
Actually the title is misleading - but they can at times seem like arrays. This just came up at work and although it is one of those things which seems obvious after, it highlights a potentially dangerous and error-prone design pattern.
Basically we had a function that looked essentially like this:
::php::
function error_prone($options) {
if ( ! isset($options['required_key'])) {
// throw error
}
// Manipulate $options['keys'] and return a result
}
At first glance this looks fair enough - while not completely robust, if a badly formed array (without required key) or a non-array is passed it should throw an error right?
Wrong. Due to PHP's doubling up of square brackets to work as character manipulation of strings.
If you don't know what I mean, try this:
::php::
$string = 'Hello World!';
echo $string[0]; // prints: H
echo $string['1']; // prints: e
Now the really unintuitive bit is highlighted on the last line. When you are specifying your character offset, PHP in all it's type-mangling wisdom, allows any variable type and casts to an int.
What does this mean for our function above? Well, in some bad cases, $options was being passed a string instead of an array. This was due to another error - but at first glance it seems our error checking should have caught that. What actually happens when a string is passed is:
$options['required_key']
return first char of$options
string since(int) 'required_key'
is0
isset($options['required_key'])
therefore returns true!- Code below mangles up some terrible return value based on chars in the string (mostly the first one) rather than actual options.
- Final result is baffling and actual source of error is obfuscated
Solution
It really isn't hard to fix: either type hint the function declaration:
::php::
function not_so_error_prone(array $options)
And handle the errors/exceptions nicely, or actually explicitly test arrayness with is_array()
.
This is a silly mistake but one that can be easily overlooked when reviewing code unless you pay close attention.