How to turn E_PARSE errors into Exception in PHP?

8

My question is:

PHP has a great feature that allows you to convert errors that can occur in an application to Exceptions . This can be done through the class ErrorException

Example:

set_error_handler(function ($errno, $errstr, $errfile, $errline ) {

    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);

});

try {
   $a = $b;
} catch(\Exception $e){
    echo $e->getMessage(); // Undefined variable: b

}

This "catch error" works perfectly for errors like E_NOTICE , E_WARNING and etc ... However, when a Parse Error ( E_PARSE ) occurs, set_error_handler is not able to capture it.

I was able to (more or less) capture this E_PARSE through the register_register_shutdown_function (it performs a function when php at the end of the script, even if execution is interrupted by E_PARSE ) in combination with the error_get_last .

  • I would like to know how to do this, so similar occurrence in the capture of errors with the set_error_handler .
  • How to proceed if you only display the error (and not prior to execution). I'll have to use a ob_start combined with a ob_end_clean within the "catcher" of the error?
  • Beforehand I already say: To say that there is no way to do this is a lie, because Laravel 4 can perfectly turn E_PARSE into exception too!

    Update

    Attheuser'srequest@gmsantos,IampostingthetransformationcodefromE_PARSEtoErrorException,whichIthinkistheclosestIwant.

    ThisiswhatIwasabletodousingregister_shutdown_function(itwasveryfast,soitdoesnothaveanyobject-oriented:)):

    <?phpob_start();echo'Olámundo';//Poressafunção,otry/catchconsegue"pegar" a exceção
    set_error_handler(function($errno, $errstr, $errfile, $errline){
    
        // Se o cara não colocar arroba, o erro é mostrado :)
    
        if (error_reporting() !== 0) {
    
            ob_clean(); // limpa o buffer e não imprime "Ólá mundo"
    
            throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
    
        }
    });
    
    // aqui não dá pra usar try/catch :(
    
    register_shutdown_function(function(){
    
        // O register_shutdown_function só pode capturar E_PARSERs provenientes de include, e não no mesmo script
    
        if ($err = error_get_last()) {
    
            ob_clean(); // limpa o buffer e não imprime "Ólá mundo"
    
            throw new ErrorException($err['message'], 0, $err['type'], $err['file'], $err['line']);
    
            /*
                Uncaught exception 'ErrorException' with message 'syntax error, unexpected '.'' 
                in C:\xampp\htdocs\teste\teste.php:4 
    
                Stack trace: 
    
                #0 [internal function]: {closure}() 
    
                #1 {main} thrown in C:\xampp\htdocs\teste\teste.php on line 4
            */
        }
    
    });
    
    // Proprositalmente para gerar uma exception não capturada pelo set_error_handler
    
    $a = @$a;
    
    try {
    
        $b = $b;
    
    } catch (Exception $e) {
    
        echo $e->getMessage(); 
    
    
        /*
            Se a variável "a" tiver um arroba colocado, essa mensagem é impressa!
            Nesse caso captura a exceção retorna: Undefined Variable: b
        */
    
    }
    
    
    try {
    
        include 'teste.php'; 
    
        /* 
            Esse include gera um E_PARSE, porém só é exibido no catch se for outros tipos de erro, 
            pois o register_shutdown_function é executado só quando o script é encerrado :(
            Não consegui capturar com o "catch"
        */
    
    } catch(\ErrorException $ee) {
    
        echo $ee->getMessage(); // Esse não imprime nada, como dito acima
    }
    

    Just reinforcing what is already written in the example: There is no way to capture E_PARSER in try/catch (at least in this script I did, there's no way)

        
    asked by anonymous 15.01.2015 / 18:15

    1 answer

    3

    Instead of giving throw to ErrorException within the register_shutdown_function callback, you can build a ErrorException and pass it to a handler that will take care of the details.

    <?php
    function handleException(Exception $e) {
        echo $e->getMessage();
    }
    
    function handleError(array $error = null) {
        $err = error_get_last();
    
        if ($err) {
            $exception =  new ErrorException(
                $err['message'], 
                $err['type'], 
                1,  
                $error['file'], 
                $err['line']
            );
            handleException($exception);
        }
    }
    
    register_shutdown_function('handleError');
    
        
    06.03.2015 / 02:42