2010-02-18 2 views
4

Кто-нибудь видит что-то не так со следующей функцией? (Edit: нет, я не думаю, что это не так, я просто дважды проверка, так как это будет вставлен в очень общий путь кода.)PHP - содержимое массива запросов с синтаксисом точки

function getNestedVar(&$context, $name) { 
    if (strstr($name, '.') === FALSE) { 
     return $context[$name]; 
    } else { 
     $pieces = explode('.', $name, 2); 
     return getNestedVar($context[$pieces[0]], $pieces[1]); 
    } 
} 

Это существенно преобразовать:

$data, "fruits.orange.quantity" 

в:

$data['fruits']['orange']['quantity'] 

для контекста, это для вида утилиты я в здании в Smarty. Мне также нужно имя для формы, поэтому мне нужна строка в форме на основе ключа и не может напрямую обращаться к переменной Smarty в Smarty.

+1

нет. должно ли быть что-то не так с этой функцией? – echo

+0

@echo, нет, см. Править выше. Я просто не уверен, что мне не хватает чего-то совершенно очевидного, почему бы не сделать это так, как я, или если есть намного более простой способ сделать это. – Nicole

ответ

7

Попробуйте итеративный подход:

function getNestedVar(&$context, $name) { 
    $pieces = explode('.', $name); 
    foreach ($pieces as $piece) { 
     if (!is_array($context) || !array_key_exists($piece, $context)) { 
      // error occurred 
      return null; 
     } 
     $context = &$context[$piece]; 
    } 
    return $context; 
} 
+0

Мне это нравится ... только одно использование взрыва произойдет и никаких проверок strstr. Путь меньше синтаксического анализа продолжается, чем у меня. – Nicole

+0

Удивительный материал спасибо. – mattl

0

Я не вижу ничего плохого в этом коде. Я тоже тестировал его.

Ответит ли это на ваш вопрос?

Редактировать: Это ИМХО немного лучше. Он не использует рекурсию и возвращает null в случае доступа к дочернему элементу без массива.

function getNestedVar(array $array, $name) { 
    $name = explode('.', $name); 
    foreach($name as $namePart) { 
     if (is_array($array)) return null; 
     if (!isset($array[$name])) return null; 
     $array = $array[$name]; 
    } 

    return $array; 
} 

Приветствия

0

Как глубоко это вложение будет? PHP имеет ограничение на рекурсию, похоже, ок. 2^16. Просто протестировал это и на глубине рекурсии 65420 PHP (5.2.9) молчал (без ошибок).

+0

Конечно, не так глубоко, но это хорошо знать. – Nicole

0

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

error_reporting(E_ALL|E_STRICT); ini_set('display_errors', 1); 
$x = array(); 
getNestedVar($x, '1.2.3.4'); 
echo 'done.'; 

(проверено с PHP 5.3.1/win32).
По какой-либо причине доступ к несуществующему элементу в getNestedVar($context[$pieces[0]]... не вызывает предупреждения, что делает его очень трудным для отладки и поиска, например. опечатка.

+0

Правильно ... Я просто хочу вернуть null, если он не существует, как это было бы при доступе к стандартным массивам. – Nicole

+0

... это хорошо. Я был просто озадачен тем, что сам php не вызывает предупреждения. – VolkerK

0

Почему вы не просто используете html .. name="fruit[orange]" достаточно .., чтобы создать массив.

1

Взгляните на это: https://gist.github.com/elfet/4713488

$dn = new DotNotation(['bar'=>['baz'=>['foo'=>true]]]); 

$value = $dn->get('bar.baz.foo'); // $value == true 

$dn->set('bar.baz.foo', false); // ['foo'=>false] 

$dn->add('bar.baz', ['boo'=>true]); // ['foo'=>false,'boo'=>true] 

И этот класс также PHPUnit тесты.

Смежные вопросы