2011-12-15 25 views
2

我有一個有趣的查詢..百科風格包括 - 週期檢測PHP

我可能已經過了簡化的例子,但虐待盡我所能來描述我的問題。

我建立一個非常簡單的實現從無到有維基的,一切都很順利,直到我意識到我需要循環檢測,以防止數據填充頁面和幸福滿溢棧堆的無限循環。

數據庫結構是基本的,還有其更復雜的,什麼是示但對於這個目的的後兩列是我們所需要的。

內容字段很簡單,它存儲頁面或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; 

} 

問題: 我將如何防止維基部分不休包括海誓山盟。 即WikiPart 1包含WikiPart2 ..但是WikiPart 2包含WikiPart1

parse或readData()函數將繼續循環。

關於

+0

那麼......你的問題在哪裏? – Nick 2011-12-15 16:51:47

+0

哦,是的,謝謝..大聲笑 – IEnumerable 2011-12-15 16:54:42

回答

2

其實如果你遇到一個循環,你不能再解決了。例如:

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

這將創建一個無限循環:

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

正如任何計算機上的資源是有限的,無限循環會導致崩潰。

那麼你能做什麼?你可以檢測到,然後通過使用堆棧錯誤了:

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)確定嵌套級別控制遞歸限制。

實際上拋出一個異常,可能不是循環引用正確的反應,但它顯示瞭如何偵破工作。您可以自行決定處理案件的方式,例如返回FALSE與否不再等解決現場..

編輯:抵達該處創意:

如果輸出HTML,你可以使用戶解決問題爲好。如果檢測到這樣的循環引用,則可以插入一些AJAX標記,以在瀏覽器中以某種形式疊加請求,該片段無法在服務器端獲得。然後這樣的覆蓋圖將再次包含循環引用(能夠再次疊加),以便用戶能夠交互地看到循環引用。

3

你可以跟蹤你的包含一個堆棧(或一組)。如果您發現該頁面,您將停止在堆棧中的某個位置。

你也可以只設置一個遞歸限制像30或什麼的,這是不是很乾淨,但工程。