Renaming the Keys of a Multidimensional Associative Array While Preserving Elements' Order

Renaming a key of an associative array in PHP is not a matter of magic, usually we can do it by assigning to a new key the value associated to the old key, and unsetting the old element. But things complicate slightly when we want to rename a key without causing the elements of the array to shuffle. In such a case, native PHP functions alone aren't enough. Creativity has to absolutely come into play.

The solution I want to share with you is a procedural function that by knowing the new keys, and the keys to rename, it uses recursion to traverse a given multidimensional associative array and return a brand new array having all the elements in their original positions and the target elements featured by the new keys.

The function is the following:

/**
 * Renames one key, or a hierarchy of keys, of a multidimensional associative array.
 *
 * @param array $array
 * @param array $old_keys Hierarchy of keys to rename.
 * @param array $new_keys Hierarchy of replacement keys. 
 *                        It must have the same number of elements of $old_keys.
 * @return array
 */
function &rename_array_keys( &$array, $old_keys, $new_keys ) {
    $new_array = array();

    // With each recursive call we extract one key 
    // from each of the two arrays of keys.
    $old_key = array_shift( $old_keys );
    $new_key = array_shift( $new_keys );

    foreach ( $array as $key => &$value ) {
        // When this check succeeds it does mean that 
        // we have found the key to rename.
        if ( $key === $old_key ) {
            if (
                // When $old_keys and $new_keys still contain elements 
                // it does mean that we are renaming a hierarchy of keys, 
                // not just a single key.
                $old_keys && $new_keys && 

                // Ensures that the recursive call is triggered only 
                // if $value is an array and actually contains 
                // the next key to rename ( $old_keys[0] ).
                isset( $value[$old_keys[0]] )
            ) {
                $new_array[$new_key] = rename_array_keys( $value, $old_keys, $new_keys ); 
            }
            else {
                $new_array[$new_key] = $value;
            }
        }
        else {
            $new_array[$key] = $value;
        }
    }

    return $new_array;
}

In the event you rename the function when you include it into your code, don't forget to edit the recursive call!

Exemplification

Suppose you have the following multidimensional associative array...

$dictionary = array(
    'a' => 1,
    'b' => array(
        'x' => 22,
        'y' => 23,
        'z' => 24
    ),
    'c' => 3
);

...and you want to rename the keys of the element $dictionary['b']['z']. The function should be called like this:

$dictionary = rename_array_keys( $dictionary, array( 'b', 'z' ), array( 'green', 'blue' ) );

The resulting array will be this one:

array(3) {
    ["a"] => int(1)
    ["green"] => array(3) {
        ["x"]    => int(22)
        ["y"]    => int(23)
        ["blue"] => int(24)
    }
    ["c"] => int(3)
}