Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP健壮包括处理错误吗?_Php_Exception_Include - Fatal编程技术网

PHP健壮包括处理错误吗?

PHP健壮包括处理错误吗?,php,exception,include,Php,Exception,Include,我有一个PHP应用程序“index.PHP”,出于各种原因,需要在另一个脚本上使用include\u once运行其他PHP脚本。另一个脚本不是很稳定,那么是否有某种方法可以安全地执行一次include_,而不会停止调用程序 i、 e: (我知道这是个多么糟糕的主意,等等,请放心,这不是生产环境的东西。)您可以 @include "fileWithBadSyntax.php"; 在我的快速测试中,它既适用于解析错误,也适用于使用trigger_error()抛出的错误 编辑:这是完全错误的

我有一个PHP应用程序“index.PHP”,出于各种原因,需要在另一个脚本上使用
include\u once
运行其他PHP脚本。另一个脚本不是很稳定,那么是否有某种方法可以安全地执行一次include_,而不会停止调用程序

i、 e:


(我知道这是个多么糟糕的主意,等等,请放心,这不是生产环境的东西。)

您可以

@include "fileWithBadSyntax.php";
在我的快速测试中,它既适用于解析错误,也适用于使用trigger_error()抛出的错误


编辑:这是完全错误的。请参阅Sleek的答案,这是正确的,尽管有些无益。

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

您可以执行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";
}
?>

在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();
 }

这些答案都不起作用。如果包含的文件中存在解析错误,则排名靠前的脚本(表示为@include())仍将终止第一个脚本

您不能eval()它,也不能尝试/捕获它,调用include或require的所有方法都将终止脚本中的所有执行

这个问题仍然悬而未决

这是PHP中的一个bug,至少从2006年起,这个功能就消失了。他们将这个bug归类为“伪造的”,因为他们声称,include()和requires()发生在编译时


如果您在运行时生成include()和/或require()的字符串参数,或者对包含运行include()的代码的字符串执行eval(),则此窗口将关闭。

以下是我能够找到的唯一真正的解决方案:

function safe_include($fn) {
        $fc = file_get_contents($fn);
        if(!eval($fc)) {
                return 0;
        }
        return 1;
}
请注意,上述代码意味着您必须从要包含的文件中取出开场白,或执行以下操作:

eval("?>" . $fc)
问题是,您不能在任何时候调用require()或include()或它们的_once()变量,并期望它们不会终止所有操作,包括任何错误处理程序。当遇到解析错误时,PHP将完全停止处理所有内容

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

eval('require($fn);'); 
…因为求值字符串中的require()仍将停止。您必须阅读内容,祈祷相关文件不包含()或进一步要求(),然后评估它


真正的解决方案是什么?跳过PHP:/

找不到包含文件的优雅解决方法

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" ); } 功能安全要求($incfile,$showfn=1){ $a=explode(“:”,get_include_path()); $a[]=”; $b=0; foreach($a为$p){ 如果(!empty($p))$p=“/”; $f=$p.$incfile; 如果(文件_存在($f)){ $b=1; 打破 } } 如果(!$b) 退出(“无法继续,需要文件”。 (($showfn)“$incfile:”)不可用或服务器已超时 ); 要求一次(“f”); }
唯一真正的解决方案(虽然不是最优雅的解决方案,但很有效)是调用另一个php解释器来解析和执行脚本,只需检查它是否产生解析错误或未检测到错误的消息,以过滤错误消息,如php parse error Bla。类似于此代码:

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


这个想法来源于PHP文档中的函数手册页。

见第二个答案,@selk是对的,你不能捕获requires/includes

我对自动加载require的解决方案是使用error\u get\u last,因此只需将其添加到基本文件中(这将处理来自requires/include的解析错误,这些错误由自动加载/子类等内容包括:

<?php 
    register_shutdown_function( "fatal_handler" );
    function fatal_handler() 
    {
        $error = error_get_last();  
        if($error !== NULL) 
        {
            if(isset($error['type']) && ($error['type'] === E_ERROR  || $error['type'] === 1 || $error['type'] === 2 || $error['type'] === 3 || $error['type'] === 4))
            {
                // do what you need to do here to make safe, I just log and use that log (to make sure other tests dont run in my case)
                Some_Class::logErrorToFile('fatal_error:' . json_encode($error));
                file_put_contents('somp_file_path_that_all_other_classes_check', 'fatal_error:' . json_encode($error));
            }
            else
            {
                Some_Class::logErrorToFile('error:' . json_encode($error)); 
            }
        }
        return;
    }

spl_autoload_register(function ($classname) {
    $classPath = str_replace("_", "/", $classname);
    $path = dirname(__FILE__) . '/../'.$classPath.'.php';
    require_once($path);  // fatal errors are logged for this runtime require, will not actually stop execution for this case, but we can handle how we deal with that now      
});

是否执行此任务,是否可以使用此方法捕获错误详细信息?此方法将使所有错误保持沉默。请参阅KyleFarris的答案,以了解将捕获错误并可选择性地使其保持沉默的方法(即自定义错误处理)事实上,Kyle的答案是更有力的,只是某人投票赞成,我不敢相信我写了它。如果它不是被接受的答案,我会删除它。一个解析错误将停止PHP在被包含的文件的中间,它不会返回到<代码> catch < /Cord>块。@ Pix0R:这当然是可行的,但是取决于它的项目范围。Wordpress肯定有办法做到这一点。如果你激活一个有语法错误或产生警告/致命错误的插件,它会告诉你并继续脚本(禁用插件并显示错误消息)。例如:“插件无法激活,因为它触发了致命错误。”虽然我相信它是通过iframe欺骗实现的,但这并不理想。但我不确定。Graben的答案,使用带有
-f
标志的解释器命令行,会起作用。它速度慢,看起来像是一个黑客,但它确实完成了任务。对于提到的bug报告,有没有值得一读的评论。这是唯一的方法,currently.使用
if
返回true或false?这听起来像是疯了吗?将解决方案转换为一行代码有什么错:
return(substr(exec(“php-l$file”),0,28)=“中未检测到语法错误”);
?ChkInc(/tmp;rm-rf/);添加了文件_existscheck for skill comment,但在一个像样的应用程序中达到此功能时,用户输入验证应该已经完成。很好,但仍然无法通过。假设在验证文件存在后删除该文件。。。。
<?php 
    register_shutdown_function( "fatal_handler" );
    function fatal_handler() 
    {
        $error = error_get_last();  
        if($error !== NULL) 
        {
            if(isset($error['type']) && ($error['type'] === E_ERROR  || $error['type'] === 1 || $error['type'] === 2 || $error['type'] === 3 || $error['type'] === 4))
            {
                // do what you need to do here to make safe, I just log and use that log (to make sure other tests dont run in my case)
                Some_Class::logErrorToFile('fatal_error:' . json_encode($error));
                file_put_contents('somp_file_path_that_all_other_classes_check', 'fatal_error:' . json_encode($error));
            }
            else
            {
                Some_Class::logErrorToFile('error:' . json_encode($error)); 
            }
        }
        return;
    }

spl_autoload_register(function ($classname) {
    $classPath = str_replace("_", "/", $classname);
    $path = dirname(__FILE__) . '/../'.$classPath.'.php';
    require_once($path);  // fatal errors are logged for this runtime require, will not actually stop execution for this case, but we can handle how we deal with that now      
});