phparraysrecursiondynamic-programming

Dynamic variable name for a multidimensional array


On my left hand I've got this "key": localisation.adresse.commune.id and many other values like this one, which are dynamic (I can't use them literally in my code as I don't know what they will be).

On the other hand I have an array like this (comes from a JSON decoded):

    Array
        (
            [localisation] => Array
                (
                    [adresse] => Array
                        (
                            [adresse1] => Le Chatelard
                            [codePostal] => 42820
                            [etat] => France
                            [commune] => Array
                                (
                                    [id] => 16418
                                )
                        )
                )
        )

I can't list all the "keys" I'm going to exploit, so I need to automatically get the value of $object['localisation']['adresse']['commune']['id'].

I've tried this but it does not work:

$test['localisation']['adresse']['commune']['id'] = 16418 ;
$var = '$test[\'localisation\'][\'adresse\'][\'commune\'][\'id\']' ;
echo $var ; // $test['localisation']['adresse']['commune']['id']
var_dump($$var) ; // NULL Notice: Undefined variable: $test['localisation']['adresse']['commune']['id']
var_dump(${$var}) ; // NULL Notice: Undefined variable: $test['localisation']['adresse']['commune']['id']

I suppose it's looking for a simple variable of a complicated name, instead of looking at a multidimensional array, but I don't know how I can do it...

Thanks for your help!


Solution

  • I see no other way except traversing the array and trying to find the keys in internal arrays, if there are any.

    I came up with two variants: recursive and iterative. They will also handle the case when the "depth" of the key and array differ, e.g. if your $key will contain more elements than the depth of the array, then the NULL will be returned, if less - then whatever is under the last key will be returned.

    Recursive variant

    $a = [
        'localisation' => [
            'adresse' => [
                'adresse1' => 'Le Chatelard',
                'codePostal' => 42820,
                'etat' => 'France',
                'commune' => [
                    'id' => 16418,
                ],
            ],
        ],
    ];
    
    $key = 'localisation.adresse.commune.id';
    
    function getValueByKeyRecursively($a, $key)
    {
        $keyList = explode('.', $key);
        $currentKey = array_shift($keyList);
    
        // Found the value
        if (empty($currentKey)) {
            return $a;
        }
    
        // No more depth to traverse or no such key
        if (!is_array($a) || !array_key_exists($currentKey, $a)) {
            return null;
        }
    
        return getValueByKeyRecursively($a[$currentKey], implode('.', $keyList));
    }
    
    var_dump(getValueByKeyRecursively($a, $key)); // outputs: int(16418)
    

    Iterative variant

    function getValueByKey(array $a, $key)
    {
        $keyList = explode('.', $key);
        $returnValue = $a;
    
        do {
            $currentKey = array_shift($keyList);
    
            // Found the value
            if ($currentKey === null) {
                break;
            }
    
            // No more depth to traverse or no such key
            if (!is_array($returnValue) || !array_key_exists($currentKey, $returnValue)) {
                return null;
            }
    
            $returnValue = $returnValue[$currentKey];
    
        } while (true);
    
        return $returnValue;
    }
    
    var_dump(getValueByKey($a, $key)); // outputs: int(16418)