Кто-нибудь видит что-то не так со следующей функцией? ( Изменить : нет, я не думаю, что что-то не так, я просто проверю дважды, так как это будет вставлено в очень распространенный путь к коду.)
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.
Попробуйте итеративный подход:
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; }
Взгляните на это: 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.
Насколько глубоко это гнездование будет? PHP имеет ограничение на рекурсию, похоже, ок. 2 ^ 16. Просто протестировал это и на глубине рекурсии 65420 PHP (5.2.9) молчал (без ошибок).
В его текущей форме ошибки / предупреждения не отображаются, если один или несколько элементов не существуют
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]]...
не вызывает предупреждения, что очень затрудняет отладку и находит, например, опечатку.
Я не вижу ничего плохого в этом коде. Я тоже тестировал его.
Отвечает ли это на ваш вопрос?
Изменить: Это ИМХО немного лучше. Он не использует рекурсию и возвращает 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; }
ура
Почему вы не просто используете html .. name="fruit[orange]"
достаточно .. сделать массив.
Посмотрите @ http://github.com/projectmeta/Stingray
Позволяет читать и записывать массив через точечную нотацию / синтаксис.
Пример: http://github.com/projectmeta/Stingray#example-usage