How do I catch a PHP fatal (`E_ERROR`) error?

前端 未结 17 2261
北荒
北荒 2020-11-21 06:21

I can use set_error_handler() to catch most PHP errors, but it doesn\'t work for fatal (E_ERROR) errors, such as calling a function that doesn\'t e

相关标签:
17条回答
  • 2020-11-21 06:53

    Fatal errors or recoverable fatal errors now throw instances of Error in PHP 7 or higher versions. Like any other exceptions, Error objects can be caught using a try/catch block.

    Example:

    <?php
    $variable = 'not an object';
    
    try {
        $variable->method(); // Throws an Error object in PHP 7 or higger.
    } catch (Error $e) {
        // Handle error
        echo $e->getMessage(); // Call to a member function method() on string
    }
    

    https://3v4l.org/67vbk

    Or you can use Throwable interface to catch all exceptions.

    Example:

    <?php
        try {
            undefinedFunctionCall();
        } catch (Throwable $e) {
            // Handle error
            echo $e->getMessage(); // Call to undefined function undefinedFunctionCall()
        }
    

    https://3v4l.org/Br0MG

    For more information: http://php.net/manual/en/language.errors.php7.php

    0 讨论(0)
  • 2020-11-21 06:55

    You can't catch/handle fatal errors, but you can log/report them. For quick debugging I modified one answer to this simple code

    function __fatalHandler()
    {
        $error = error_get_last();
    
        // Check if it's a core/fatal error, otherwise it's a normal shutdown
        if ($error !== NULL && in_array($error['type'],
            array(E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING,
                  E_COMPILE_ERROR, E_COMPILE_WARNING,E_RECOVERABLE_ERROR))) {
    
            echo "<pre>fatal error:\n";
            print_r($error);
            echo "</pre>";
            die;
        }
    }
    
    register_shutdown_function('__fatalHandler');
    
    0 讨论(0)
  • I developed this function to make it possible to "sandbox" code that could cause a fatal error. Since exceptions thrown from the closure register_shutdown_function don't get emitted from the pre-fatal error call stack, I'm forced to exit after this function to provide a uniform way of using it.

    function superTryCatchFinallyAndExit( Closure $try, Closure $catch = NULL, Closure $finally )
    {
        $finished = FALSE;
        register_shutdown_function( function() use ( &$finished, $catch, $finally ) {
            if( ! $finished ) {
                $finished = TRUE;
                print "EXPLODE!".PHP_EOL;
                if( $catch ) {
                    superTryCatchFinallyAndExit( function() use ( $catch ) {
                        $catch( new Exception( "Fatal Error!!!" ) );
                    }, NULL, $finally );                
                } else {
                    $finally();                
                }
            }
        } );
        try {
            $try();
        } catch( Exception $e ) {
            if( $catch ) {
                try {
                    $catch( $e );
                } catch( Exception $e ) {}
            }
        }
        $finished = TRUE;
        $finally();
        exit();
    }
    
    0 讨论(0)
  • 2020-11-21 06:56

    I developed a way to catch all error types in PHP (almost all)! I have no sure about E_CORE_ERROR (I think will not works only for that error)! But, for other fatal errors (E_ERROR, E_PARSE, E_COMPILE...) works fine using only one error handler function! There goes my solution:

    Put this following code on your main file (index.php):

    <?php
        define('E_FATAL',  E_ERROR | E_USER_ERROR | E_PARSE | E_CORE_ERROR |
                E_COMPILE_ERROR | E_RECOVERABLE_ERROR);
    
        define('ENV', 'dev');
    
        // Custom error handling vars
        define('DISPLAY_ERRORS', TRUE);
        define('ERROR_REPORTING', E_ALL | E_STRICT);
        define('LOG_ERRORS', TRUE);
    
        register_shutdown_function('shut');
    
        set_error_handler('handler');
    
        // Function to catch no user error handler function errors...
        function shut(){
    
            $error = error_get_last();
    
            if($error && ($error['type'] & E_FATAL)){
                handler($error['type'], $error['message'], $error['file'], $error['line']);
            }
    
        }
    
        function handler( $errno, $errstr, $errfile, $errline ) {
    
            switch ($errno){
    
                case E_ERROR: // 1 //
                    $typestr = 'E_ERROR'; break;
                case E_WARNING: // 2 //
                    $typestr = 'E_WARNING'; break;
                case E_PARSE: // 4 //
                    $typestr = 'E_PARSE'; break;
                case E_NOTICE: // 8 //
                    $typestr = 'E_NOTICE'; break;
                case E_CORE_ERROR: // 16 //
                    $typestr = 'E_CORE_ERROR'; break;
                case E_CORE_WARNING: // 32 //
                    $typestr = 'E_CORE_WARNING'; break;
                case E_COMPILE_ERROR: // 64 //
                    $typestr = 'E_COMPILE_ERROR'; break;
                case E_CORE_WARNING: // 128 //
                    $typestr = 'E_COMPILE_WARNING'; break;
                case E_USER_ERROR: // 256 //
                    $typestr = 'E_USER_ERROR'; break;
                case E_USER_WARNING: // 512 //
                    $typestr = 'E_USER_WARNING'; break;
                case E_USER_NOTICE: // 1024 //
                    $typestr = 'E_USER_NOTICE'; break;
                case E_STRICT: // 2048 //
                    $typestr = 'E_STRICT'; break;
                case E_RECOVERABLE_ERROR: // 4096 //
                    $typestr = 'E_RECOVERABLE_ERROR'; break;
                case E_DEPRECATED: // 8192 //
                    $typestr = 'E_DEPRECATED'; break;
                case E_USER_DEPRECATED: // 16384 //
                    $typestr = 'E_USER_DEPRECATED'; break;
            }
    
            $message =
                '<b>' . $typestr .
                ': </b>' . $errstr .
                ' in <b>' . $errfile .
                '</b> on line <b>' . $errline .
                '</b><br/>';
    
            if(($errno & E_FATAL) && ENV === 'production'){
    
                header('Location: 500.html');
                header('Status: 500 Internal Server Error');
    
            }
    
            if(!($errno & ERROR_REPORTING))
                return;
    
            if(DISPLAY_ERRORS)
                printf('%s', $message);
    
            //Logging error on php file error log...
            if(LOG_ERRORS)
                error_log(strip_tags($message), 0);
        }
    
        ob_start();
    
        @include 'content.php';
    
        ob_end_flush();
    ?>
    
    0 讨论(0)
  • 2020-11-21 06:57

    If you are using PHP >= 5.1.0 Just do something like this with the ErrorException class:

    <?php
        // Define an error handler
        function exception_error_handler($errno, $errstr, $errfile, $errline ) {
            throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
        }
    
        // Set your error handler
        set_error_handler("exception_error_handler");
    
        /* Trigger exception */
        try
        {
            // Try to do something like finding the end of the internet
        }
        catch(ErrorException $e)
        {
            // Anything you want to do with $e
        }
    ?>
    
    0 讨论(0)
  • 2020-11-21 06:59

    Not really. Fatal errors are called that, because they are fatal. You can't recover from them.

    0 讨论(0)
提交回复
热议问题