2011-12-15 48 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或什么的,这是不是很干净,但工程。