2013-07-09 5 views
2

Я пытаюсь получить элемент из многомерного массива через строку, которая описывает путь в массив (например, first.second.third).Почему при попытке разрешить многомерный массив возникает ошибка «Неопределенная переменная»?

Я выбрал подход, как показано здесь (also available on ideone):

<?php 
    // The path into the array 
    $GET_VARIABLE = "a.b.c"; 
    // Some example data 
    $GLOBALS["a"]= array("b"=>array("c"=>"foo")); 

    // Construct an accessor into the array 
    $variablePath = explode(".", $GET_VARIABLE); 
    $accessor = implode("' ][ '", $variablePath); 
    $variable = "\$GLOBALS[ '". $accessor . "' ]"; 

    // Print the value for debugging purposes (this works fine) 
    echo $GLOBALS["a"]["b"]["c"] . "\n"; 
    // Try to evaluate the accessor (this will fail) 
    echo $$variable; 
?> 

Когда я запускаю сценарий, он будет печатать две строки:

foo 
PHP Notice: Undefined variable: $GLOBALS[ 'a' ][ 'b' ][ 'c' ] in ... 

Итак, почему же это не оценить должным образом?

+1

"[" не нужен побег символ? – VeNoMiS

+0

@VeNoMiS: Если я убегу от него с обратной косой чертой, эта обратная косая черта также появится в сообщении об ошибке. Так что, я думаю, нет. –

+0

Я имею в виду \\ [btw я пробовал: P – VeNoMiS

ответ

5

Я думаю, что нотация $$ принимает только имя переменной (т. Е. Имя переменной). Вы на самом деле пытаетесь прочитать переменную с именем «$GLOBALS[ 'a' ][ 'b' ][ 'c' ]», которой не существует.

В качестве альтернативы ($GET_VARIABLE, кажется, ваша входная строка), вы можете попробовать это:

$path = explode('.', $GET_VARIABLE); 
echo $GLOBALS[$path[0]][$path[1]][path[2]]; 

Wrap это в соответствующем цикле, чтобы сделать его более динамичным; это кажется тривиальным.

+0

Я вижу, это имеет смысл. Могли бы вы, возможно, порекомендовать альтернативный подход? –

+1

Фактически нашел решение здесь: http://stackoverflow.com/questions/7688664/php-best-way-of-setting-a-value-in-a-multi-dimensional-array-when-the-pathway-i Спасибо –

2

Похоже, что PHP обрабатывает всю вашу строку как имя переменной, а не как массив.

Вместо этого вы можете попробовать использовать следующий подход, так как это также, вероятно, будет проще.

<?php 
    // The path into the array 
    $GET_VARIABLE = "a.b.c"; 
    // Some example data 
    $GLOBALS["a"]= array("b"=>array("c"=>"foo")); 

    // Construct an accessor into the array 
    $variablePath = explode(".", $GET_VARIABLE); 
    //$accessor = implode("' ][ '", $variablePath); 
    //$variable = "\$GLOBALS[ '". $accessor . "' ]"; 

    // Print the value for debugging purposes (this works fine) 
    echo $GLOBALS["a"]["b"]["c"] . "\n"; 
    // Try to evaluate the accessor (this will fail) 
    echo $GLOBALS[$variablePath[0]][$variablePath[1]][$variablePath[2]]; 
?> 
+0

Количество элементов в пути было бы переменной, хотя, поэтому я искал эту оценку в первую очередь. –

1

Вот код, который я написал для доступа к переменным $ _SESSION через точечную нотацию. Вы должны легко перевести его.

<?php 
$key = "a.b.c";  
$key_bits = explode(".", $key); 

$cursor = $_SESSION; 

foreach ($key_bits as $bit) 
{ 
    if (isset($cursor[$bit])) 
    { 
     $cursor = $cursor[$bit]; 
    } 
    else 
    { 
     return false; 
    } 
} 

return $cursor; 
1

Вот еще одно решение, используя вспомогательную функцию:

function GetValue($path, $scope = false){ 
    $result = !empty($scope) ? $scope : $GLOBALS; 

    // make notation uniform 
    $path = preg_replace('/\[([^\]]+)\]/', '.$1', $path); // arrays 
    $path = str_replace('->', '.', $path); // object properties 

    foreach (explode('.', $path) as $part){ 
     if (is_array($result) && array_key_exists($part, $result)){ 
      $result = $result[$part]; 
     } else if (is_object($result) && property_exists($result, $part)){ 
      $result = $result->$part; 
     } else { 
      return false; // erroneous 
     } 
    } 
    return $result; 
} 

И пример использования:

// Some example data 
$GLOBALS["a"] = array(
    'b' => array(
    'c' => 'foo', 
    'd' => 'bar', 
    ), 
    'e' => (object)array(
    'f' => 'foo', 
    'g' => 'bar' 
    ) 
); 
$bar = array(
    'a' => $GLOBALS['a'] 
); 

echo $GLOBALS['a']['b']['c'] . "\n"; // original 

// $GLOBALS['a']['b']['c'] 
echo GetValue('a.b.c')  . "\n"; // traditional usage 
// $GLOBALS['a']['b']['c'] 
echo GetValue('a[b][c]')  . "\n"; // different notation 
// $bar['a']['b']['c'] 
echo GetValue('a.b.c', $bar) . "\n"; // changing root object 
// $GLOBALS['a']['e']->f 
echo GetValue('a[e]->f')  . "\n"; // object notation 
Смежные вопросы