2011-12-15 9 views
2

を、私はやや興味深いのクエリを持っている...ウィキペディアスタイルは、 - 周期検出PHP

私は簡単な例を介して持っていますが、病気の私の問題を記述するために最善を尽くします。

私は、サイクル・ディテクションがデータの無限ループを防ぎ、スタック・ヒープをうまくオーバーフローさせないようにするまで、うまくいっています。

データベース構造は基本的なものであり、表示されているものよりも複雑ですが、この記事の目的上、2つの列だけが必要です。

コンテンツフィールドはまっすぐで、ページまたはWikiPartリンクのコンテンツ、つまり[[n]]を別の部分にリンクするために格納し、リンクは[[n]]としてリンクされ、{{n }}。

+---------------------------+ 
| id | Content   | 
+---------------------------+ 
| 1 | see {{2}} here | 
+---------------------------+ 
| 2 | {{1}} here [[4]] | 
+---------------------------+ 
| 4 | {{1}}    | 
+---------------------------+ 



$html_for_screen = readData($this->Content); 

function readData($wikipage) { 

    $str = ""; 

    //Convert any wiki links to HTML Links 
    $wikipage = Converter::convertWikink($wikipage); 

    //Get ALL Include Link matches into array 
    $wiki_inc = RegEx::getMatches(wikipage); 

    //Iterate through the Matches 
    foreach($wiki_inc as $wiki) { 
     //traverse through each match. 
     //but I assume here is where I would eventually have the trouble 
     //With infinant loops 
     $str .= readData($wiki); 
    } 

    return $str; 

} 

質問: どのように私は際限なくお互いを含めウィキパーツを防止するであろう。 すなわちWikiPart1にはWikiPart2が含まれていますが、WikiPart2にはWikiPart1が含まれています

parseまたはreadData()関数はループを繰り返します。

について

+0

so ...ここにあなたの質問はありますか? – Nick

+0

ああ、ありがとう..lol – IEnumerable

答えて

2

実際にサイクルが発生した場合は、もう解決できません。例:すべてのコンピュータリソースが限られていると、無限ループがクラッシュにつながる

1 -> 2 -> 1 -> 2 -> ... 

1: {{2}} 
2: {{1}} 

これは無限ループを作成します。

あなたは何をすることができますか?あなたはそれを検出し、スタックを使用してエラー可能性:

function readData($wikipage) 
{ 
    static $stack = array(); 
    if (in_array($wikipage, $stack)) 
    { 
     throw new Exception(sprintf('Circular reference detected: %s -> %s', implode(' -> ', $stack), $wikipage)); 
    } 
    $stack[] = $wikipage; 

    ... (your existing code) 

    array_pop($stack); 
} 

また、あなたが入れ子のレベルを決定するためにcount($stack)を使用して再帰制限を制御することができます。

実際に例外をスローすることは、循環参照の適切な反応ではないかもしれませんが、検出の仕組みを示しています。ケースにどのように対処するかを自分で決めることができます(例:出力は、ユーザーが同様の問題を解決する作ることができるHTMLの場合

FALSEを返すか、もはやなどのフィールドを解決しません。..

編集:がここに創造的な取得。このような循環参照が検出された場合、サーバー側で取得できなかったスニペットをブラウザー内のオーバーレイの何らかの形式で要求するAJAXマーカーを挿入することができます。そのようなオーバレイは、ユーザが周期的な参照をインタラクティブに見ることができるように、循環参照を再び含む(再びオーバレイすることができる)。

+0

$ n値、$ stack [$ n] = $ wikipageを割り当てるべきか、それとも配列の上に置くことによってPHPが処理するのですか? – IEnumerable

+0

PHPはこれを扱います、 '$ stack [] = $ value'は[' array_push'](http://php.net/array_push)のようなものなので、別の変数や '$ stack [ count($ stack)] = $ value'となります。 – hakre

+0

私は毎日、愛するPHP、より良い! – IEnumerable

3

あなたはスタック(またはセット)であなたの包含を追跡することができます。ページの中にスタックのどこかに入れようとしているものがある場合は、そのページを停止します。

また、30などの再帰制限を設定することもできますが、これはあまりクリーンではありませんが、機能します。

関連する問題