2012-02-19 8 views
3

私はこの情報をデータベースに格納する目的でjson_encodedebug_backtraceという出力を試しています。再帰を削除するには?

問題は、再帰が含まれることがあります。私が気にしない何か。再帰が検出された時点で*RECURSION*とすれば十分です。

どうすればよいですか?

+2

データベースの値をJSONとしてエンコードする必要はありません。 – alex

+0

serializeを使用してください:) – Vyktor

+0

エラーレポートの一部としてこのデータを保存する必要があります。私は関係を気にしませんが、バックトレース情報のためだけに2つのテーブルを追加したくないと言います。 – Gajus

答えて

0

本当に良い代替手段になるでしょう。

ツリーをトラバースする方法はありません。すべての配列とオブジェクトを保持し、それらが同じ値を参照しているかどうかを確認してください。

オブジェクトの場合は、spl_object_hashを使用できるため、少し簡単です。配列の場合

、私は今考えることができる唯一の方法は、以下の

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

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

    return $result; 

} 

は賢く方法があるかどう聞くのが大好きだです。

あなたは再帰を中断することに興味があり、それほど多くないのでの参照これは高価である必要はありません。あなたが横断している間にスタックを保つだけで、両親と比較するだけです。

EDIT

自分自身を助けることができませんでした。これにより、配列参照は破棄されますが、オブジェクト参照は中断されます。あなたが1つを把握することができますを確認します。

を(警告:醜いコード)

<?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

関連する問題