2010-11-11 37 views
1

我正在構建一個小模板系統,並且正在尋找一種使用點調用多維關聯數組的方法。例如:在模板中調用多維關聯數組

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

然後,在我的模板,如果我想顯示 '狗',我會把:

{} a.four-legged.smart.best

+0

你嘗試過什麼?你是否嘗試過寫一個表達式來替換帶有方括號和引號的點? – GWW 2010-11-11 18:44:06

+0

理論上,是的。但那麼我的結果將是一個字符串,而不是一個有效的變量名稱。這將是「$ a ['四條腿'] ['聰明'] ['最好']」。 – MichaelBrett 2010-11-11 18:48:56

+0

@GWW你真的不想做評估,如果你能幫助它。 – 2010-11-11 18:52:35

回答

5

好,給出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 
} 

所以你可以撥打:

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

如果你想寫的元素,這不是更難(你只需要使用引用,幾張支票爲默認值,如果路徑不存在)...:

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; 
} 

編輯:由於這是一個模板系統,它可能是值得的「編譯」數組到一個單一的維度一次,而不是每一次(由於性能原因)遍歷它...

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; 
} 

所以,這將轉換:

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

進入

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

那麼你的查詢只成爲$value = isset($compiledArray[$path]) ? $compiledArray[$path] : '';代替$value = getElementFromPath($array, $path);

它換預先計算的在線速度(內環路速度)...

+0

出於好奇,你爲什麼要在那裏做一個is_array檢查? – MichaelBrett 2010-11-11 19:26:11

+0

哪裏?在上面的代碼中有兩個'is_array'檢查...你指的是哪一個('setElementFromPath'中的或者'compileWithDots'中的那個)? – ircmaxell 2010-11-11 19:27:47

+0

我也注意到,設置一個元素會擦除所有其他元素。 – MichaelBrett 2010-11-11 19:28:44