Rinominare le Chiavi di un Array Associativo Multidimensionale Preservando l'Ordine degli Elementi

Rinominare una chiave di un array associativo in PHP non è una questione di magia, di solito possiamo farlo assegnando ad una nuova chiave il valore associato alla vecchia chiave, e facendo un unset del vecchio elemento. Ma le cose si complicano un po' quando vogliamo rinominare una chiave senza che gli elementi dell'array vengano rimescolati. In casi come questo, le funzioni PHP native non bastano. La creatività deve necessariamente entrare in gioco.

La soluzione che voglio condividere con te è una funzione procedurale che note le nuove chiavi, e le chiavi da rinominare, ricorre alla ricorsione per scorrere un dato array associativo multidimensionale e restituire un array nuovo di zecca avente tutti gli elementi nelle posizioni originali e gli elementi target caratterizzati dalle nuove chiavi.

La funzione è la seguente:

/**
 * Rinomina una chiave, o una gerarchia di chiavi, di un array 
 * associativo multidimensionale.
 *
 * @param array $array
 * @param array $old_keys Gerarchia di chiavi da rinominare.
 * @param array $new_keys Gerarchia di chiavi sostitutive. 
 *                        Deve avere lo stesso numero di elementi di $old_keys.
 * @return array
 */
function &rename_array_keys( &$array, $old_keys, $new_keys ) {
    $new_array = array();

    // Con ogni chiamata ricorsiva estraiamo una chiave 
    // da ogniuno dei due array di chiavi.
    $old_key = array_shift( $old_keys );
    $new_key = array_shift( $new_keys );

    foreach ( $array as $key => &$value ) {
        // Quando questo controllo ha esito positivo significa che
        // abbiamo trovato la chiave da rinominare.
        if ( $key === $old_key ) {
            if (
                // Quando $old_keys e $new_keys contengono ancora elementi
                // significa che stiamo rinominando una gerachia di chiavi,
                // non semplicemente una sigola chiave.
                $old_keys && $new_keys && 

                // Assicura che la chiamata ricorsiva venga eseguita solo
                // se $value è un array ed effettivamente contiene
                // la successiva chiave da rinominare ( $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;
}

Nel caso in cui dovessi rinominare la funzione quando la includerai nel tuo codice, non dimenticare di editare la chiamata ricorsiva!

Esemplificazione

Supponi di avere il seguente array associativo multidimensionale...

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

...e che tu voglia rinominare le chiavi dell'elemento $dictionary['b']['z']. La funzione andrebbe chiamata in questo modo:

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

L'array risultante sarà questo:

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