Categories
Posts

PHP array_map Callback Expects The Full Namespace

The array_map function in PHP has a quirk ( I know, shocker ) that I’ve managed to forget several times. Hopefully writing it here will cement it in my memory.

Using array_map isn’t hard, here is a very contrived example:

[sourcecode lang=”php”]
namespace EXAMPLE;

function lowercase_string( $name ) {
return strtolower( $name );
}

function lowercase_array( $names ) {
return array_map( ‘lowercase_string’, $names );
}

print_r( lowercase_array( [
‘Bill’,
‘Max’,
‘Julie’,
‘Norm’
] ) );
echo "n";
[/sourcecode]

You feed an array to lowercase_array() and it will return lower cased versions of all the array entries. Do you know what happens when you run this code?

[sourcecode lang=”plain”]
PHP Warning: array_map() expects parameter 1
to be a valid callback, function ‘lowercase_string’
not found or invalid function name in
/home/josephscott/tmp/array-map.php on line 9
[/sourcecode]

( I broke this up into multiple lines to make it easier to read )

How can lowercase_string not be a valid callback? It is even defined right there in the same file. The answer to this question is in the very first line of my example.

When using array_map() inside of a namespace you must provide the full namespace reference to the callback. In this case that means replacing lowercase_string with EXAMPLElowercase_string:

[sourcecode lang=”php”]
namespace EXAMPLE;

function lowercase_string( $name ) {
return strtolower( $name );
}

function lowercase_array( $names ) {
return array_map( ‘EXAMPLElowercase_string’, $names );
}

print_r( lowercase_array( [
‘Bill’,
‘Max’,
‘Julie’,
‘Norm’
] ) );
echo "n";
[/sourcecode]

Running this corrected version gives us what we’d expect:

[sourcecode lang=”plain”]
Array
(
[0] => bill
[1] => max
[2] => julie
[3] => norm
)
[/sourcecode]

I think the reason that I keep forgetting this is because it feels more obvious that array_map() should know it is already in a namespace and try to dereference the callback based on that namespace first, the same way a regular function call would. This feels like a violation of the principle of least astonishment (POLA).

While the array_map() documentation makes no mention of the namespace requirement for the callback, it does appear to be the intended behavior. A PHP bug was filed describing this exact issue. It was closed as “this is not a bug”.