簡體   English   中英

致命錯誤:嵌套級別太深 - 遞歸依賴?

[英]Fatal error: Nesting level too deep - recursive dependency?

我有一個復雜的嵌套對象層次結構,所有子對象(存儲在父類中的對象數組)包含一個鏈接回其父級的屬性:相當簡單和直接,沒有實際問題。 如果我對層次結構中的任何對象執行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父級中,使父關系“正確”......我已經開始這樣做了。 但是,我對錯誤很感興趣,並想知道是否有其他人遇到過它(以及你自己如何處理它)。

如果使用==而不是===比較遞歸對象,也會出現這種情況

如果需要比較實際對象實例,請始終使用嚴格比較運算符===因為它僅比較對象是否引用同一類的同一實例。

簡短說明:

如果使用$object == $objectToCompareWith比較對象,PHP會將第一個對象的每個屬性和值與第二個對象進行比較。 這種比較是對象的遞歸,這些對象是被比較對象的屬性。

這意味着如果兩個對象共享一個以對象作為其值的屬性,那么PHP會對這些屬性對象進行相同的==比較。 現在,只要那些屬性對象是遞歸的(例如,自引用對象),比較就會向下遞歸,直到達到最大嵌套級別。

正如Josh Stuart和mazatwork的評論中所述,通過將各自的$strict參數設置為true ,可以在使用像in_array()array_search()這樣的數組函數時強制進行嚴格的比較。

Richard Lord:“嵌套級別太深 - 遞歸依賴?”

PHP手冊:“比較對象”

看起來像自我引用代碼中的PHP限制並嘗試使用print_rvar_dumpvar_export顯示它,或使用in_array搜索它。 基本上,如果對象被循環引用,那么這些函數無法知道在何處停止遞歸。

根據這個錯誤報告重現這個的最簡單方法是:

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

其他錯誤報告也提到了它,還有一些測試用例。 我會說如果只是在var_dump觸發,你不應該過多擔心它。 如果這是出於調試目的,我肯定是第二個Wrikken關於xdebug的建議。

有時候(但很少,因為這種爭用的有效性有限)會發生這種情況,並且只要你的代碼正常工作,我就不會過多考慮var_dump (調試工具,而不是生產工具)無法應對用它。 但是,如果仍然需要 var_dump工作,我可以衷心地建議運行xdebug,在其中可以設置var_dump將顯示的max-depth,字符串轉儲的最大長度以及最大子項數。

我得到了和你一樣的錯誤,但是在一個完全不同的場景中。 我發布了答案,以防其他人以同樣的方式來到這里。

如果您正在嘗試使用對象數組進行自定義排序(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偶爾會返回一個對象而不是一個數字。 一旦我確定它總是返回一個數字然后錯誤就消失了。

也許這有助於某人。

對我來說,一個解決方案是在php.ini中引發pcre.recursion_limit 但是,當您閱讀其他答案時,這更像是一種臨時解決方法,因為問題很可能在於您自己的代碼。

您可以使用魔術方法__toString來定義到字符串的自定義轉換。 在實現__toString時,查看您的對象並避免過於遞歸,並且一切都應該沒問題。 永遠不要忘記並不小心調用var_dump,var_export,print_r等。

一旦定義了__toString方法,下面的工作就很好了:

echo $ yourObjectHere;

這是我目前的解決方案,效果很好,但我仍然想要保護我不要忘記不調用var_dump,var_export和print_r。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM