私はこの情報をデータベースに格納する目的でjson_encode
debug_backtrace
という出力を試しています。再帰を削除するには?
問題は、再帰が含まれることがあります。私が気にしない何か。再帰が検出された時点で*RECURSION*
とすれば十分です。
どうすればよいですか?
私はこの情報をデータベースに格納する目的でjson_encode
debug_backtrace
という出力を試しています。再帰を削除するには?
問題は、再帰が含まれることがあります。私が気にしない何か。再帰が検出された時点で*RECURSION*
とすれば十分です。
どうすればよいですか?
本当に良い代替手段になるでしょう。
ツリーをトラバースする方法はありません。すべての配列とオブジェクトを保持し、それらが同じ値を参照しているかどうかを確認してください。
オブジェクトの場合は、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);
?>
私はそれが繰り返し機能と関係しているとは思わない。 debug_backtraceの出力には、 'object'と 'args'キーを使用して循環参照を含めることができます。 – Evert
は、私は同様の問題を自分で持っていました。私はあまりにも、再帰参照をすべて通過して削除した関数でそれを解決しました。皮肉なことに、それ自体は再帰的な機能です!
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;
}
最初の呼び出しのために、あなたはそれはそれが再発するときのためにだけあります、第二引数に渡す必要はありません:これは私が思い付いたものです。
私が間違っている場合は私を修正しますが、スタックパラメータは、下位のものよりもむしろすべての層のスタックを変更するので、ここで参照によって渡すべきではないようです。 –
これは正しくありません。あなたは間違った出力を生成する深さ優先検索を行っています – Benubird
データベースの値をJSONとしてエンコードする必要はありません。 – alex
serializeを使用してください:) – Vyktor
エラーレポートの一部としてこのデータを保存する必要があります。私は関係を気にしませんが、バックトレース情報のためだけに2つのテーブルを追加したくないと言います。 – Gajus