Catching PHP Parser error when using include

2020-07-14 01:16发布

I have a file called functions.php.

This file consists includes to all the other function files, for example:

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

I would like to catch errors where when I screw a code in one of those files, It wouldn't give the error to the entire system.

For example, if there is a parser error in foo_functions.php it will just not include it in functions.php.

Is that possible?

标签: php try-catch
6条回答
我欲成王,谁敢阻挡
2楼-- · 2020-07-14 01:22

Parser errors are fatal errors, so you can't catch them. See this question and answer for more details.

What you can do if you can run exec() is call php -l thefilename.php and check the result. See the manual for information on how this works. There are a few problems here, however:

  • This is extremely dangerous, because you are passing information to the command line. You absolutely must filter any user input very carefully, or you would be giving the user very broad access to your system.
  • exec() is often disabled, as it should be, because of the extremely high security risks of using it incorrectly.
  • There's really no good reason to include a file that you haven't already validated for syntax errors. If this is for plugins or something, then I understand your reasoning. If it is code you have control over, however, you should validate before putting it into production.
查看更多
做个烂人
3楼-- · 2020-07-14 01:23

This code can check if file is exist or not, if file exist than include it.

<? 
    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'; 
    }
?>

And this one help you get syntax errors (PHP 7+ only)

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


?>

so if you use PHP 7+ you may use:

<? 
    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楼-- · 2020-07-14 01:25

include() and include_once() return false if they fail. You can use this to check if the included files were successful.

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

By changing the echos to handle your error logic, you should be able to do what you are asking.

查看更多
放我归山
5楼-- · 2020-07-14 01:28

What if you put

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

at the beginning of foo_functions.php ?

查看更多
放我归山
6楼-- · 2020-07-14 01:36

The solution that I am using feels like a band-aid solution, but it will give you control back.

The idea is to use "eval()" to first check for errors. Also, ignore errors with the @ in the beginning. Of course you will need to be careful with eval, so don't ever let users feed anything to it.

    // 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));
    }

Please note that I think "file_get_contents + eval" = "require", or very close to it, so you may be able to just skip the require-part.

查看更多
手持菜刀,她持情操
7楼-- · 2020-07-14 01:37

As of PHP 7, most eval/include errors, such as ParseError can be catched:

try {
  include_once(__DIR__ . '/test.php');
} catch (\Throwable $e) {
  var_dump($e);
}
查看更多
登录 后发表回答