在模板中调用多维关联数组

I'm building a small template system and i'm looking for a way to invoke multidimensional associative arrays using dots. For example:

$animals = array(
          'four-legged' => array (
                          'cute' => 'no',
                          'ugly' => 'no',
                          'smart' => array('best' => 'dog','worst' => 'willy')
                          ),
          '123' => '456',
          'abc' => 'def'
);

Then, in my template, if I wanted to show 'dog', I would put:

{a.four-legged.smart.best}

Well, given a string with four-legged.smart.worst:

function getElementFromPath(array $array, $path) {
    $parts = explode('.', $path);
    $tmp = $array;
    foreach ($parts as $part) {
        if (!isset($tmp[$part])) {
            return ''; //Path is invalid
        } else {
            $tmp = $tmp[$part];
        }
    }
    return $tmp; //If we reached this far, $tmp has the result of the path
}

So you can call:

$foo = getElementFromPath($array, 'four-legged.smart.worst');
echo $foo; // willy

And if you want to write elements, it's not much harder (you just need to use references, and a few checks to default the values if the path doesn't exist)...:

function setElementFromPath(array &$array, $path, $value) {
    $parts = explode('.', $path);
    $tmp =& $array;
    foreach ($parts as $part) {
        if (!isset($tmp[$part]) || !is_array($tmp[$part])) {
            $tmp[$part] = array();
        }
        $tmp =& $tmp[$part];
    }
    $tmp = $value;
}

Edit: Since this is in a template system, it may be worth while "compiling" the array down to a single dimension once, rather than traversing it each time (for performance reasons)...

function compileWithDots(array $array) {
    $newArray = array();
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $tmpArray = compileWithDots($value);
            foreach ($tmpArray as $tmpKey => $tmpValue) {
                $newArray[$key . '.' . $tmpKey] = $tmpValue;
            }
        } else {
            $newArray[$key] = $value;
        }
    }
    return $newArray;
}

So that would convert:

$animals = array(
 'four-legged' => array (
  'cute' => 'no',
  'ugly' => 'no',
  'smart' => array(
   'best' => 'dog',
   'worst' => 'willy'
  )
 ),
 '123' => '456',
 'abc' => 'def'
);

Into

array(
    'four-legged.cute' => 'no',
    'four-legged.ugly' => 'no',
    'four-legged.smart.best' => 'dog',
    'four-legged.smart.worst' => 'willy',
    '123' => '456',
    'abc' => 'def',
);

Then your lookup just becomes $value = isset($compiledArray[$path]) ? $compiledArray[$path] : ''; instead of $value = getElementFromPath($array, $path);

It trades pre-computing for inline speed (speed within the loop)...