Intereting Posts
Как использовать модели в очереди Laravel Вырезать пробелы внутри переменной в PHP Здесь он работает из WHILE. Внутри это не работает, почему? Многомерный массив массивов PHP PHP получает разницу между двумя массивами объектов простой счетчик посетителей совместное использование файлов cookie через домены на одном хосте Как добавить параметры продукта на странице категории в opencart 2.0 Динамическое добавление строк в таблицу HTML Использование JavaScript и получение значения текстового поля для каждого текстового поля путем отправки кнопки Использование xpath в объекте PHP SimpleXML, пространства имен SOAP + (не работает ..) PHP: предупреждение: включить не удалось открыть поток нет такого файла или каталога в Windows Загрузить файл не работает с ajax php mysql_insert_id (); не работает Закрытие PHP: не удается записать файлы? Случайное число в диапазоне с использованием PHP

Неустранимая ошибка: уровень вложенности слишком глубокий – рекурсивная зависимость?

У меня сложная иерархия вложенных объектов со всеми дочерними объектами (хранится массив объектов в родительском классе), содержащий свойство, связывающее его с родителем: довольно простой и понятный, без реальных проблем. Если я сделаю var_dump любого объекта в иерархии, я получу рекурсивную ссылку в дампе, точно так, как я ожидал.

FIRSTGEN _children array of objects of type SECONDGEN SECONDGEN #1 _parent object of type FIRSTGEN _children array of objects of type THIRDGEN THIRDGEN #1 _parent object of type SECONDGEN THIRDGEN #2 _parent object of type SECONDGEN SECONDGEN #2 _parent object of type FIRSTGEN _children array of objects of type THIRDGEN THIRDGEN #3 _parent object of type SECONDGEN 

Недавно я добавил несколько новых элементов в эту иерархию, и они не соответствуют совершенно одинаковой схеме. Они хранятся в массиве объектов в родительском элементе верхнего уровня, но содержат свойство, связывающее их, а не с их родителем, а с родным братом. Когда я делаю var_dump сейчас, я получаю «Неустранимая ошибка: слишком высокий уровень вложенности – рекурсивная зависимость?».

 FIRSTGEN _children_1 array of objects of type SECONDGEN_1 SECONDGEN_1 #1 _parent object of type FIRSTGEN _children array of objects of type THIRDGEN THIRDGEN #1 _parent object of type SECONDGEN_1 THIRDGEN #2 _parent object of type SECONDGEN_1 SECONDGEN_1 #2 _parent object of type FIRSTGEN _children array of objects of type THIRDGEN THIRDGEN #3 _parent object of type SECONDGEN_1 _children_2 array of objects of type SECONDGEN_2 SECONDGEN_2 #1 _parent object of type SECONDGEN_1 

Все остальное в коде работает правильно, за исключением того, что var_dump (). Я попытался создать более простой пример, чтобы продемонстрировать проблему, чтобы я мог привести пример, задавая этот вопрос; но не смогли воспроизвести его в коротком тесте, только в моем более сложном коде.

Я знаю, что решение состоит в том, чтобы реорганизовать отношения так, чтобы мой массив _children_2 объектов SECONDGEN_2 содержался в соответствующем родителе SECONDGEN_1, делая родительское отношение «правильным» … Я уже начал это делать. Однако я заинтригован этой ошибкой и задаюсь вопросом, встречался ли кто-нибудь еще (и как вы справлялись с этим самим).

Похоже на ограничение PHP в коде саморегуляции и попытку отобразить его с помощью print_r , var_dump , var_export или поиска через него с помощью in_array . В принципе, нет возможности для этих функций знать, где остановить рекурсию, если объект ссылается cirularly.

Согласно этому отчету об ошибке, самый простой способ воспроизвести это :

 $outText = var_export( $GLOBALS, true ); print_r($outText) ; 

В других отчетах об ошибках упоминается об этом, а также в нескольких тестах. Я бы сказал, что если это вызвано только в var_dump вы не должны слишком беспокоиться об этом. Я определенно рекомендую второе предложение Wrikken о xdebug, если это для целей отладки.

Это также возникает, если вы сравниваете рекурсивные объекты, используя == вместо ===

Если вам нужно сравнить фактические экземпляры объектов, всегда используйте оператор строгого сравнения === поскольку он сравнивается только в том случае, если объекты относятся к одному и тому же экземпляру того же класса.

Краткое объяснение:

Если вы сравниваете объекты с помощью $object == $objectToCompareWith , PHP сравнивает каждый атрибут и значение первого объекта со вторым. Это сравнение рекурсивно над объектами, которые являются свойствами сравниваемых объектов.

Это означает, что если оба объекта совместно используют атрибут с объектом в качестве его значения, PHP делает то же == сравнение между этими объектами атрибутов. Теперь, как только объекты этих атрибутов будут рекурсивными (например, объект самореференции), сравнение также повторяется, пока не будет достигнут максимальный уровень вложенности.

Как указано в комментариях Джоша Стюарта и mazatwork, строгое сравнение может быть принудительно при использовании функций массива, таких как in_array() и array_search() путем установки их соответствующего $strict параметра в значение true .

Ричард Лорд: «Уровень гнездования слишком глубокий – рекурсивная зависимость?»

Руководство по PHP: «Сравнение объектов»

Иногда (но редко, поскольку существуют ограниченные значения, используемые для таких contrustcs), это происходит, и пока ваш код работает правильно, я бы не стал думать, что var_dump (инструмент отладки, а не производственный) не может справиться с этим. Однако, если вам все еще нужно работать var_dump , я могу от всей души рекомендовать запустить xdebug, в котором вы можете установить max-depth, var_dump будет показан var_dump , максимальную длину дампа строк и максимальное количество детей.

Я получал ту же ошибку, что и вы, но в совершенно другом сценарии. Я отправляю ответ на случай, если кто-то еще будет таким же, как и я.

В случае, если вы пытаетесь создать собственный сортировку (usort) с массивом объектов, вот что мне нужно сделать:

 function cmp($a, $b) { if($a->num_estimates == $b->num_estimates) return 0; return($a->num_estimates < $b->num_estimates) ? -1 : 1; } $c = usort(Company::$companies, "cmp"); 

Оказалось, что $object->num_estimates иногда возвращал объект вместо числа. Как только я убедился, что он всегда возвращал номер, ошибка исчезла.

Вы можете использовать магический метод __toString для определения пользовательского преобразования в строку. Просмотрите свой объект и не заходите слишком глубоко через рекурсии при реализации __toString, и все должно быть хорошо. Просто никогда не забывайте и случайно вызывайте var_dump, var_export, print_r и т. Д.

Как только метод __toString был определен, следующее работает красиво:

echo $ yourObjectHere;

Это мое текущее решение, которое работает хорошо, но мне все равно хотелось бы что-то защитить меня от забывания не вызывать var_dump, var_export и print_r.

Может быть, это помогает кому-то.

Для меня решением было поднять pcre.recursion_limit в php.ini. Это скорее временное обходное решение, когда вы читаете другие ответы, хотя проблема, скорее всего, лежит внутри вашего собственного кода.