Kamafeather Kamafeather - 3 months ago 10
PHP Question

How to write getter/setter to access multi-level array by key names?

I've to implement a setter in PHP, that allows me to specify the key, or sub key, of an array (the target), passing the name as a dot-separated-keys value.

Given the following code:

$arr = array('a' => 1,
'b' => array(
'y' => 2,
'x' => array('z' => 5, 'w' => 'abc')
),
'c' => null);

$key = 'b.x.z';
$path = explode('.', $key);


From the value of
$key
I want to reach the value 5 of
$arr['b']['x']['z']
.

Now....
given a variable value of
$key
and a different
$arr
value (with different deepness).

How can I set the value of the element pointed by
$key
?



For the getter
get()
I wrote this code:

public static function get($name, $default = null)
{
$setting_path = explode('.', $name);
$val = $this->settings;

foreach ($setting_path as $key) {
if(array_key_exists($key, $val)) {
$val = $val[$key];
} else {
$val = $default;
break;
}
}
return $val;
}


To write a setter is more difficult because I succeed in reaching the right element (from the
$key
), but I am not able to set the value in the original array and I don't know how to specify the key all at once.

Should I use some kind of backtracking? Or can I avoid it?

Answer

Assuming $path is already an array via explode, use references. You need to add in some error checking in case of invalid $path etc...

$key = 'b.x.z';
$path = explode('.', $key);

Getter

function get($array, $path) {
    $temp = &$array;

    foreach($path as $key) {
        $temp =& $temp[$key];
    }
    return $temp;
}

$value = get($arr, $path);

Setter

Make sure to define $array to be passed by reference &$array:

function set(&$array, $path, $value) {
    $temp = &$array;

    foreach($path as $key) {
        $temp =& $temp[$key];
    }
    $temp = $value;
}

set($arr, $path, 'some value');

Or if you want to return the updated array (because I'm bored):

function set($array, $path, $value) {
    $temp = &$array;

    foreach($path as $key) {
        $temp =& $temp[$key];
    }
    $temp = $value;

    return $array;
}

$arr = set($arr, $path, 'some value');
Comments