2012-02-19 122 views
3

我試圖json_encodedebug_backtrace輸出用於將此信息存儲在數據庫中。如何刪除遞歸?

問題是有時它包含遞歸。我不在乎的東西。在檢測到遞歸的地方只需要*RECURSION*就足夠了。

我該怎麼做?

+2

數據庫值不需要編碼爲JSON。 – alex

+0

使用序列化:) – Vyktor

+0

嗯,我需要存儲這些數據作爲錯誤報告的一部分。我不關心關係,或者我應該說,我不想爲追溯信息創建額外的2個表。 – Gajus

回答

0

序列化確實是一個很好的選擇。

由於缺乏這一點,所以沒有其他方法來遍歷樹,保留所有數組和對象,看看它們是否引用相同的值。

由於可以使用spl_object_hash,所以對象更容易一些。

對於數組,我現在能想到的唯一的辦法就是以下

function referToTheSame(&$arr1, &$arr2) { 
    // copy 
    $tmp = $arr1; 

    $arr1 = 'foo'; 
    $result = ($arr2==='foo'); 
    $arr1 = $tmp; 

    return $result; 

} 

很想聽到,如果有一個更聰明的方法。

哦,既然你只是想打破遞歸,而不是那麼多任何參考這不會是那麼昂貴。只需在遍歷時保留一個堆棧,所以只需要與父母進行比較。

編輯

控制不住自己。這會中斷數組引用,但不會引用對象。當然,你可以搞懂這個問題:

(警告:醜陋的代碼)

<?php 

$structure = array(
    0 => 'foo', 
    1 => 'bar', 
); 

$structure[] =& $structure; 

function traverse($item, &$stack) { 

    foreach($item as $key=>&$value) { 

     if (is_array($value)) { 

      // Checking if this array already appeared in the stack 
      foreach($stack as &$array2) { 

       // Copy 
       $tmp = $array2; 
       $array2 = 'foo'; 
       if ($value==='foo') { 
        $array2 = $tmp; 

        // We need to create another temporary value, to break the 
        // reference. 
        $newValue = '* INCEPTION *'; 
        $value =& $newValue; 
        continue 2; 
       } else { 
        $array2 = $tmp; 
       } 

      } 

      $stack[] =& $value; 
      traverse($value, $stack); 
      array_pop($stack); 

     } 

    } 

} 

$stack = array(); 
$stack =& $structure; 
traverse($structure, $stack); 

print_r($structure); 

?> 
+0

我不認爲它與循環函數有關。 debug_backtrace的輸出仍然可以通過'object'和'args'鍵包含循環引用。 – Evert

1

我也有類似的問題我自己。我也用一個經過並刪除了所有遞歸引用的函數來解決它。諷刺的是,這樣做的功能本身就是遞歸的!這是我想出了:

public static function remove_recursion(&$object, &$stack = array()) { 
    if ((is_object($object) || is_array($object)) && $object) { 
     if (!in_array($object, $stack, true)) { 
      $stack[] = $object; 
      foreach ($object as &$subobject) { 
       self::remove_recursion($subobject, $stack); 
      } 
     } else { 
      $object = "***RECURSION***"; 
     } 
    } 
    return $object; 
} 

對於第一個呼叫,你不需要在第二個參數來傳遞,這只是在那裏它再次出現時。

+0

糾正我,如果我錯了,但它看起來像堆棧參數不應該通過引用傳遞在這裏,因爲它修改堆棧的所有層遞歸,而不是隻有一個下層。 –

+0

這是不正確的。您正在執行深度優先搜索,這會產生錯誤的輸出 – Benubird