2012-01-28 18 views
14

私はちょうど(私のペットプロジェクトdump_rで私の再帰検出アルゴリズムを作り直しました)PHPで無限配列再帰を検出していますか?オブジェクトの再帰を検出

https://github.com/leeoniya/dump_r.php

あまりにも難しいことではない - あなたがオブジェクトインスタンスの固有の内部IDを取得するために)(spl_object_hashを使用他のノードをダンプしながらそれを辞書に格納して比較する。

アレイ再帰検出のために、私はちょっと困惑していますが、何か助けになるものは見つかりませんでした。 php自体は再帰を識別することができますが、それはあまりにも遅すぎるようです。 EDIT:NVM、それは

$arr = array(); 
$arr[] = array(&$arr); 
print_r($arr); 

:)をする必要がある場合、それが起こることは、再帰スタック内のすべてのトラックを保つことに頼ると、他のすべての配列要素に対して浅い比較を行う必要があるのでしょうか?

ありがとうございます。
ありがとうございました!

+0

lol - eeewwwww。 – leeoniya

+1

あなたの質問に対する答えではありませんが、再帰を示す文字列に対して 'print_r($ var、true) 'をテストするソリューションがあります。これはあなたが得ることができるほど厄介ですが、うまくいきます...適切な妥協のために[ここ](http://noteslog.com/post/detecting-recursive-dependencies-in-php-composite-values/)を参照してください。 – Basic

+0

例へのリンクを含むように私のコメントを削除/編集しましたが、私は同意します。それは臭いです – Basic

答えて

9

、私はここを参照してください唯一の解決策は、参照することにより、配列を反復処理し、その中に任意の値を設定することで、これを使用:私はこの記事http://noteslog.com/post/detecting-recursive-dependencies-in-php-composite-values/と、この解決策を見つけましたそれはあなたが前にあったかどうかを確認するために存在している場合は、後でチェック:

function iterate_array(&$arr){ 

    if(!is_array($arr)){ 
    print $arr; 
    return; 
    } 

    // if this key is present, it means you already walked this array 
    if(isset($arr['__been_here'])){ 
    print 'RECURSION'; 
    return; 
    } 

    $arr['__been_here'] = true; 

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

    // print your values here, or do your stuff 
    if($key !== '__been_here'){ 
     if(is_array($value)){ 
     iterate_array($value); 
     } 

     print $value; 
    } 
    } 

    // you need to unset it when done because you're working with a reference... 
    unset($arr['__been_here']); 

} 

あなたが代わりに参照の値を受け入れる別の関数に、この関数をラップすることもできますが、あなたは上の2番目のレベルから再帰通知を得るでしょう。 print_rも同じことをすると思います。

+0

**これは私が望んでいた解決策です - シンプルで素晴らしい。 – leeoniya

3

私が間違っていると誰かが私を修正しますが、PHPは現時点で実際に再帰を検出しています。あなたの割り当ては、単に追加のサイクルを作成するだけです。例は次のようになります。予想通り

array(1) { [0]=> &array(1) { [0]=> *RECURSION* } } 

になります

$arr = array(); 
$arr = array(&$arr); 


再帰を検出する方法はちょっと不思議ですが、私はGoogleに着手しました。そのためPHPの呼び出しごとの値メカニズムの

function hasRecursiveDependency($value) 
{ 
    //if PHP detects recursion in a $value, then a printed $value 
    //will contain at least one match for the pattern /\*RECURSION\*/ 
    $printed = print_r($value, true); 
    $recursionMetaUser = preg_match_all('@\*RECURSION\*@', $printed, $matches); 
    if ($recursionMetaUser == 0) 
    { 
     return false; 
    } 
    //if PHP detects recursion in a $value, then a serialized $value 
    //will contain matches for the pattern /\*RECURSION\*/ never because 
    //of metadata of the serialized $value, but only because of user data 
    $serialized = serialize($value); 
    $recursionUser = preg_match_all('@\*RECURSION\*@', $serialized, $matches); 
    //all the matches that are user data instead of metadata of the 
    //printed $value must be ignored 
    $result = $recursionMetaUser > $recursionUser; 
    return $result; 
} 
+0

あなたは正しいです。遅くはない。しかし、私はまだネイティブ関数の外でこれを行う方法が必要です。 – leeoniya

+0

このソリューションは、大規模な構造に大きな負担をかけており、制御不能な深さのprint_r()やシリアライズに依存しているため、私が望んでいたものではありません。 、しかし、http://www.phpsadness.com/: – leeoniya