2009-10-06 88 views
14

我有一个PHP应用程序“index.php”,由于各种原因,需要在其他脚本上使用include_once来运行其他PHP脚本。那另一个脚本不是很稳定,那么有没有办法做一个安全include_once不会停止调用者?强大的PHP包含处理错误?

即:

<?php 

safely_include_once('badfile.php'); // MAY throw syntax error, parse error, other badness 
echo "I can continue execution after error"; 

?> 

(我知道什么是一个坏主意,这可能是等,放心,这不是生产环境的东西。)

回答

6

你可以

@include "fileWithBadSyntax.php"; 

从我的快速测试中,它对解析错误或trigger_error()引发的错误都有效。

编辑:这是完全错误的。看到潜行的答案,这是正确的,如果有点无益。

+0

工作是否可以通过这种方法捕获错误细节? – 2009-10-06 19:13:54

+0

这种方法可以消除所有错误。请参阅KyleFarris的答案,该方法可以捕获错误并可以选择保持安静(IE,自定义错误处理)。 – 2009-10-06 19:46:00

+0

事实上,凯尔的答案更强大 – timdev 2009-10-06 19:47:19

2

是否有可能更改您的架构并将“badfile.php”转换为Web服务?不要将其直接包含到代码库中,而要通过网络调用它并解析或包含其输出。这样可以避免解析错误,如果badfile.php的环境受到适当限制(使用safe_mode或运行具有有限权限的单独Web服务器进程),还可以避免潜在的恶意代码。

+1

@ pix0r:这当然会起作用,但取决于他的项目范围,它可能只是有点矫枉过正,不够好看。 – KyleFarris 2009-10-08 15:13:28

2

你可以做一个try/catch块

<?php 
try { 
    include("someFile.php"); 
} catch (Exception $e) { 
    // Should probably write it to a log file, but... for brevity's sake: 
    echo 'Caught exception: ', $e->getMessage(), "\n"; 
} 
?> 

现在,它只会包含的文件,如果没有错误。如果出现错误,它会跳过这些东西并写入异常(例如,在注释中,最好写入日志文件或其他东西)。

欲了解更多信息: http://us2.php.net/manual/en/language.exceptions.php

+10

解析错误会在包含文件中间停止PHP,并且它不会返回到“catch”块。 – erjiang 2009-10-07 17:46:15

+0

嗯......你说得对。哪里哪里。 – KyleFarris 2011-05-25 20:11:40

-1

在badfile.php你可以把它返回一个值:

<?php 
//inestable instructions. 


return true; ?> 

然后在主文件,你可以这样做:的

<?php 

if (require($badFile)) { 
    //if it was true continue with normal execution 
} else { 
    echo "Error: ". error_get_last(); 
} 
36

无这些答案将起作用。如果在包含的文件中存在解析错误,那么对@include()说的顶级投票仍然会终止第一个脚本。

你不能eval()它,你不能尝试/捕捉它,并且每个调用include或require的方法都将终止全部在脚本中的执行。

这个问题仍然是OPEN和UNSOLVED。

http://bugs.php.net/bug.php?id=41810

这是PHP的一个bug,并且至少自2006年他们归类错误是“虚假的”,因为,他们声称这一功能一直缺少的,包括()和需要()发生在编译期时间。

如果在RUNTIME中生成包含()和/或require()的字符串参数,或者在包含运行include()的代码的字符串上执行eval(),则会出现窗口。

+0

最佳答案恕我直言 – Janning 2011-05-25 07:52:18

+0

必须有一种方式,Wordpress能够做到这一点。如果您激活了一个语法错误或生成警告/致命错误的插件,它会告诉您并继续执行脚本(禁用插件并显示错误消息)。例如:“插件无法激活,因为它触发了致命错误。”不过,我相信它通过iframe欺骗来做到这一点,但这并不理想。但我不确定。 – 2013-05-03 18:56:07

+0

Graben的答案,使用解释器命令行和'-f'标志,将会起作用。它很慢,看起来像一个黑客,但它确实完成了工作。 – 2013-07-02 14:15:21

-3

这里是唯一真正的解决方案,我已经能够找到:

function safe_include($fn) { 
     $fc = file_get_contents($fn); 
     if(!eval($fc)) { 
       return 0; 
     } 
     return 1; 
} 

注意的是,上面的代码意味着你必须从你的要被包含的文件取出开幕式上发言,还是做以下:

eval("?>" . $fc) 

的问题是,你不能调用需要()或include()或它们的_once()在任何一点的变体,并期望他们不要终止一切,包括任何错误处理程序。当遇到分析错误时,PHP将完全停止处理所有事情。

唯一的例外是eval()中的字符串。问题是,虽然,你不能真正做到这一点:

eval('require($fn);'); 

......因为需要()的eval'd字符串将仍然停止内。你必须阅读内容,祈祷有问题的文件不包括()或需要()更多,并eval()它。

真正的解决方案?跳过PHP。 :/

2

优美的解决方法包括文件未找到....

 
function safe_require($incfile, $showfn=1) { 
    $a = explode(":", get_include_path()) ; 
    $a[] = ""; 
    $b = 0; 
    foreach($a as $p) { 
    if(!empty($p)) $p .= "/"; 
    $f = $p.$incfile; 
    if(file_exists($f)) { 
     $b = 1; 
     break; 
    } 
    } 
    if(!$b) 
    exit("Cannot proceed, required file " . 
      (($showfn) ? $incfile : "") . " is unavailable or server has timed out." 
     ); 
    require_once("$f"); 
} 
+0

非常好,但仍然failable。想象一下,在你验证它存在之后,文件将被删除.... – Pacerier 2013-07-13 01:50:36

10

唯一真正的解决方案,以为不是最优雅之一,但工作原理是在另一个PHP解释器来解析调用和执行该脚本,除了检查它是否产生分析错误或未检测到错误消息来过滤错误消息,如PHP Parse Error blablabla。这样的代码呢:

<?php 
function ChkInc($file){ 
    return file_exists($file) && (substr(exec("php -l $file"), 0, 28) == "No syntax errors detected in"); 
} 
?> 

这个想法来自gillis' commentinclude功能手册页在PHP文档。

+2

这是目前唯一的方法。 – 2013-07-02 14:13:51

+1

使用'if'返回true或false?这听起来不是疯狂吗?将你的解决方案转换成单行代码有什么问题:'return(substr(exec(“php -l $ file”),0,28)==“在检测到没有语法错误”);'? – trejder 2015-05-08 07:40:52

+0

对,更新了单行版本的答案。 – Graben 2015-05-08 17:58:51