How to convert all keys in a multi-dimenional array to snake_case?

This is the modified function I have used, taken from soulmerge's response:

function transformKeys(&$array)
{
  foreach (array_keys($array) as $key):
    # Working with references here to avoid copying the value,
    # since you said your data is quite large.
    $value = &$array[$key];
    unset($array[$key]);
    # This is what you actually want to do with your keys:
    #  - remove exclamation marks at the front
    #  - camelCase to snake_case
    $transformedKey = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', ltrim($key, '!')));
    # Work recursively
    if (is_array($value)) transformKeys($value);
    # Store with new key
    $array[$transformedKey] = $value;      
    # Do not forget to unset references!
    unset($value);
  endforeach;
}

Here's a more generalized version of Aaron's. This way you can just plug the function you want to be operated on for all keys. I assumed a static class.

public static function toCamelCase ($string) {
  $string_ = str_replace(' ', '', ucwords(str_replace('_',' ', $string)));
  return lcfirst($string_);
}

public static function toUnderscore ($string) {
  return strtolower(preg_replace('/([^A-Z])([A-Z])/', "$1_$2", $string));
}

// http://stackoverflow.com/a/1444929/632495
function transformKeys($transform, &$array) {
  foreach (array_keys($array) as $key):
    # Working with references here to avoid copying the value,
    # since you said your data is quite large.
    $value = &$array[$key];
    unset($array[$key]);
    # This is what you actually want to do with your keys:
    #  - remove exclamation marks at the front
    #  - camelCase to snake_case
    $transformedKey = call_user_func($transform, $key);
    # Work recursively
    if (is_array($value)) self::transformKeys($transform, $value);
    # Store with new key
    $array[$transformedKey] = $value;
    # Do not forget to unset references!
    unset($value);
  endforeach;
}

public static function keysToCamelCase ($array) {
  self::transformKeys(['self', 'toCamelCase'], $array);
  return $array;
}

public static function keysToUnderscore ($array) {
  self::transformKeys(['self', 'toUnderscore'], $array);
  return $array;
}

Although this may not be an exact answer to the question, but I wanted to post it here for people who are searching for elegant solution for changing key case in multidimensional PHP arrays. You can also adapt it for changing array keys in general. Just call a different function instead of array_change_key_case_recursive

// converts all keys in a multidimensional array to lower or upper case
function array_change_key_case_recursive($arr, $case=CASE_LOWER)
{
  return array_map(function($item)use($case){
    if(is_array($item))
        $item = array_change_key_case_recursive($item, $case);
    return $item;
  },array_change_key_case($arr, $case));
}