【问题标题】:Catching PHP Parser error when using include使用包含时捕获 PHP 解析器错误
【发布时间】:2014-02-21 07:07:30
【问题描述】:

我有一个名为 functions.php 的文件。

此文件包含所有其他函数文件,例如:

include_once("user_functions.php");
include_once("foo_functions.php");

我想捕捉错误,当我在其中一个文件中插入代码时,它不会将错误传递给整个系统。

例如,如果 foo_functions.php 中存在解析器错误,则它不会将其包含在 functions.php 中。

这可能吗?

【问题讨论】:

    标签: php try-catch


    【解决方案1】:

    从 PHP 7 开始,可以捕获大多数 eval/include 错误,例如 ParseError:

    try {
      include_once(__DIR__ . '/test.php');
    } catch (\Throwable $e) {
      var_dump($e);
    }
    

    【讨论】:

    • 感谢您提醒我指定 Throwable 而不是 Exception,我已经习惯使用它来捕获所有可能的东西。
    • 经过测试,肯定可以在 PHP 7.3 和 PHP 7.4 中使用。只需确保您已包裹 right 文件并部署/上传了 right 文件。
    • stackoverflow 的小宝石以出色的解决方案而闻名。谢谢
    【解决方案2】:

    解析器错误是致命错误,因此您不能catch 它们。 See this question and answer for more details.

    如果您可以运行exec(),您可以做的是调用php -l thefilename.php 并检查结果。 See the manual for information on how this works。但是,这里有一些问题:

    • 这是非常危险的,因为您将信息传递到命令行。您绝对必须非常仔细地过滤任何用户输入,否则您将给予用户非常广泛的系统访问权限。
    • exec() 经常被禁用,这是应该的,因为错误使用它会带来极高的安全风险。
    • 确实没有充分的理由包含尚未验证语法错误的文件。如果这是用于插件或其他东西,那么我理解你的推理。但是,如果是您可以控制的代码,则应在将其投入生产之前进行验证。

    【讨论】:

    • 这实际上是因为我正在使用实时系统,我不希望意外忘记它;在一个函数中会导致在系统上工作的所有用户都收到解析器错误。我想更合理的解决方案是在离线机器上工作并在一切就绪后上传最新版本,但我有点懒惰。
    【解决方案3】:

    此代码可以检查文件是否存在,如果文件存在则包含它。

    <? 
        if(!is_file('user_functions.php')){
            //There is no file user_functions.php . You may use file_put_contents('user_functions.php','<? //content ?>');
        }else{
            //ther is file user_functions.php, so include it.
            include 'user_functions.php'; 
        }
    ?>
    

    这个可以帮助您解决语法错误(仅限 PHP 7+)

    <?
        try {
            include('user_functions.php');
        }catch (ParseError $e) {
            echo 'Error: '.$e->getMessage();
            //syntax error, unexpected end of file, expecting ',' or ';'
        }
    
    
    ?>
    

    所以如果你使用 PHP 7+,你可以使用:

    <? 
        if(!is_file('user_functions.php')){
            echo 'Error: file is not exist';
        }else{
            //check errors
            try {
                include('user_functions.php');
            }catch (ParseError $e) {
                echo 'Error: '.$e->getMessage();
                //syntax error, unexpected end of file, expecting ',' or ';'
            }
        }
    ?>
    

    【讨论】:

      【解决方案4】:

      如果你放了

      error_reporting(E_ALL);
      ini_set("display_errors", 1);
      

      在 foo_functions.php 的开头?

      【讨论】:

      • 我确实希望在错误发生时看到它们。我只是希望能够使用 try catch 捕获解析错误。不确定这是否可能。
      【解决方案5】:

      include()include_once() 如果失败则返回 false。您可以使用它来检查included 文件是否成功。

      if (!include('user_functions.php'))
         echo 'user functions failed to include';
      if (!include('foo_functions.php'))
         echo 'foo_functions failed to include';
      

      通过更改echos 来处理您的错误逻辑,您应该能够按照您的要求进行操作。

      【讨论】:

      • 我指的是解析器错误,而不是文件是否存在这种错误。
      【解决方案6】:

      我使用的解决方案感觉像是一种创可贴解决方案,但它会让你重新控制。

      这个想法是使用“eval()”来首先检查错误。此外,请忽略开头带有 @ 的错误。当然,你需要小心 eval,所以永远不要让用户向它提供任何东西。

          // first "eval" the file to see if it contains errors
          $txt = file_get_contents($template_filename);
      
          // eval starts out in php-mode.  get out of it.
          $txt = '?' . '>' . $txt;
          ob_start();
          $evalResult = @eval($txt);
          ob_end_clean();
      
          // if there are no errors
          if($evalResult !== FALSE) {
              require($template_filename);
          } else {
              error_log(print_r(error_get_last(), TRUE));
          }
      

      请注意,我认为 "file_get_contents + eval" = "require" 或非常接近,所以您可以跳过要求部分。

      【讨论】:

        猜你喜欢
        • 2015-11-06
        • 1970-01-01
        • 2013-11-29
        • 1970-01-01
        • 2014-11-18
        • 2016-08-01
        • 2017-05-06
        • 2016-10-26
        • 2012-01-25
        相关资源
        最近更新 更多