General function to recursively array_map() for any callback function?

I’m trying to write a function where you can recursively array_map() for any valid function.

A specific function would be:

function addslashes_deep($value) {
	if( is_array($value) ) return array_map('addslashes_deep', $value);
	else return addslashes($value);
}

Here’s my attempt at a general function:

function array_map_deep($value, $function) {
	if( is_array($value) ) return array_map( 'array_map_deep', $value, array_fill(0, count($value), $function) );
	else eval('$retval = '.$function.'($value);');
	return $retval;
}

However my code is buggy - the array keys are not kept intact. For instance given the code,

$array = array("Review"=>"Something's happening. \\"Quote here.\\" And more.", array("Inside"=>'What\\'s more: "And how". But not.', "Second"=>'Here. &something. Double: " Single: \\' End.'), 'Last'=>'Nothing\\'s happening.');
print_r(array_map_deep($array, 'addslashes'));

My function outputs:

Array
(
    [0] => Something\\'s happening. \\"Quote here.\\" And more.
    [1] => Array
        (
            [0] => What\\'s more: \\"And how\\". But not.
            [1] => Here. &something. Double: \\" Single: \\' End.
        )

    [2] => Nothing\\'s happening.
)

The mapping of addslashes() seems to work, but it is remapping the array keys, e.g. “Review” to “0”. The specific function, addslashes_deep(), does not have this problem.

What is incorrect in my code?


function array_map_deep($array, $callback) {
    $new = array();
    foreach ($array as $key => $val) {
        if (is_array($val)) {
            $new[$key] = array_map_deep($val, $callback);
        } else {
            $new[$key] = call_user_func($callback, $val);
        }
    }
    return $new;
}

You can also just use a variable for a function name. ex:


$function_name( $array )

Thanks a lot, works like a charm :slight_smile:

Edit: Minor change to deal with possible non-array inputs -


function array_map_deep($array, $callback) {
    $new = array();
    if( is_array($array) ) foreach ($array as $key => $val) {
        if (is_array($val)) {
            $new[$key] = array_map_deep($val, $callback);
        } else {
            $new[$key] = call_user_func($callback, $val);
        }
    }
    else $new = call_user_func($callback, $array);
    return $new;
}

If you want to make it more robust, you might want to consider not just using is_array(), but also check if it implements ArrayAccess


if (is_array($foo) || $foo instanceof ArrayAccess) {

}

There’s also array_walk_recursive(). You can just copy the array before calling it if you don’t want the original modified.