У меня сложная иерархия вложенных объектов со всеми дочерними объектами (хранится массив объектов в родительском классе), содержащий свойство, связывающее его с родителем: довольно простой и понятный, без реальных проблем. Если я сделаю 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. Это скорее временное обходное решение, когда вы читаете другие ответы, хотя проблема, скорее всего, лежит внутри вашего собственного кода.