JavaScript / HTML / CSS / PHP

24May/10Off

PHP Error Handler, Tracking you project bugs

Errors
Error reporting
Error handler

There’s a way to hide those ugly error outputs from PHP, and not just that you can track them, log them and manage them.

We have different type of errors some of them are possible to catch and others aren’t, in this post you will learn how to build your own error tracker, but first lets learn something about PHP errors, check the different type of errors in the following list.

Value Constant Description PHP
1 E_ERROR Fatal run-time errors. Errors that cannot be recovered from. Execution of the script is halted
2 E_WARNING Non-fatal run-time errors. Execution of the script is not halted
4 E_PARSE Compile-time parse errors. Parse errors should only be generated by the parser
8 E_NOTICE Run-time notices. The script found something that might be an error, but could also happen when running a script normally
16 E_CORE_ERROR Fatal errors at PHP startup. This is like an E_ERROR in the PHP core 4
32 E_CORE_WARNING Non-fatal errors at PHP startup. This is like an E_WARNING in the PHP core 4
64 E_COMPILE_ERROR Fatal compile-time errors. This is like an E_ERROR generated by the Zend Scripting Engine 4
128 E_COMPILE_WARNING Non-fatal compile-time errors. This is like an E_WARNING generated by the Zend Scripting Engine 4
256 E_USER_ERROR Fatal user-generated error. This is like an E_ERROR set by the programmer using the PHP function trigger_error() 4
512 E_USER_WARNING Non-fatal user-generated warning. This is like an E_WARNING set by the programmer using the PHP function trigger_error() 4
1024 E_USER_NOTICE User-generated notice. This is like an E_NOTICE set by the programmer using the PHP function trigger_error() 4
2048 E_STRICT Run-time notices. PHP suggest changes to your code to help interoperability and compatibility of the code 5
4096 E_RECOVERABLE_ERROR Catchable fatal error. This is like an E_ERROR but can be caught by a user defined handle (see also set_error_handler()) 5
6143 E_ALL All errors and warnings, except of level E_STRICT 5

The error_reporting function has a parameter to set which type of error you want to show.

You can set to 0 if you don’t want to show nothing

To show the common errors

error_reporting(E_ERROR | E_WARNING | E_PARSE);

If you’re picky , this will help you to code better

error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);

This is the default set from php.ini

error_reporting(E_ALL  ^ E_NOTICE);

This show everything

I use this, I care more about these ones

error_reporting(E_ERROR | E_PARSE);


You need to create a new PHP file that's going to handle the errors and you have to load it in every PHP file that runs by itself  I mean that is not loaded in another PHP (but don't worry using require_once it will be loaded just once)...but well this depends of the structure of your project .

//At the beginning of your php code
require_once('error_handler.php');

There's a function called set_error_handler with this one you can catch many errors but  there are some E_FATAL errors that are impossible to catch with this function, so theres a trick to catch them and show something else instead.

1
2
3
4
5
6
7
8
ini_set('display_errors', 'On');
#here we are setting our normal error handler
set_error_handler('errorHandler');
#here we wrap the the error in tags
ini_set('error_prepend_string', '<phpfatalerror>');
ini_set('error_append_string', '</phpfatalerror>');
#and all the output will pass through here our fatal error handler
ob_start('fatalErrorHandler');

So in your function you should classified which kind of error you are receiving

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    function errorHandler($error_number, $error_string, $error_file, $error_line, $error_context)
    {
        $error_title    = "";
        $error_array    = array();
        $backtrace      = array();
       
        switch ($error_number)
        {
            case E_FATAL:
                $error_title = "Fatal Error";
                break;
            case E_ERROR:              
                $error_title = "Error";                  
                break;
            case E_WARNING:            
                $error_title = "Warning";                
                break;
            case E_PARSE:              
                $error_title = "Parse Error";            
                break;
            case E_NOTICE:              
                $error_title = "Notice";                
                break;
            case E_CORE_ERROR:          
                $error_title = "Core Error";            
                break;
            case E_CORE_WARNING:        
                $error_title = "Core Warning";          
                break;
            case E_COMPILE_ERROR:      
                $error_title = "Compile Error";          
                break;
            case E_COMPILE_WARNING:    
                $error_title = "Compile Warning";        
                break;
            case E_USER_ERROR:          
                $error_title = "User Error";            
                break;
            case E_USER_WARNING:        
                $error_title = "User Warning";          
                break;
            case E_USER_NOTICE:        
                $error_title = "User Notice";            
                break;
            case E_STRICT:              
                $error_title = "Strict Notice";          
                break;
            case E_RECOVERABLE_ERROR:  
                $error_title = "Recoverable Error";      
                break;
            default:                    
                $error_title = "Unknown error ($error_number)";
                break;
        }
      //Here you code to track errors
   }

With this code from above you can send emails or log errors in Data Base.

The second function you need is the one it takes the fatal errors from the tags, and we show a custom error html.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    function fatalErrorHandler($bufferContent)
    {
        define('E_FATAL', 'efatal');
        $output     = $bufferContent;
        $matches    = array();
        $errors     = "";
       
        if ( preg_match('|<phpfatalerror>.*</phpfatalerror>|s', $output, &$matches) )
        {
            foreach ($matches as $match)
            {
                $errors .= strip_tags($match) . "\n\n---\n\n";
            }
           
            $var = errorHandler('efatal', 'Fatal Error', 'unknown', 'unknown', $errors);
            $filename = HTML_DIR . "unavailable.html";
            $handle = fopen($filename, "r");
            $contents = fread($handle, filesize($filename));
            fclose($handle);
            $output =  $contents;
        }
        return $var;
    }

Well if you use this code I fully recommend you to take all the possible variables that might be part of the error.
There's a function call debug_backtrace that returns you the array of all the trace you code did. so I recommend you log it too.

Update: If you are using the PHP version 5.3 or earlier, now comes with the new error levels E_DEPRECATED & E_USER_DEPRECATED

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Reddit
  • StumbleUpon
  • Twitter
Comments (11) Trackbacks (68)
  1. You left out E_USER_DEPRECATED and E_DEPRECATED.

  2. You are right! I’ll update this thanks! :D

  3. Using E_ERROR and E_PARSE only, is very bad practice. This leads to a much harder debugging time, and gives a lot of headache for developers who are also working on the project, but use the suggested E_ALL | E_STRICT level.

  4. You might want to add a call to set_exception_handler too, to track any unhandled PHP exceptions:

    http://php.net/manual/en/function.set-exception-handler.php

  5. I totally agree with WishCow hiding warnings is a huge source of bugs. If they exists it’s for a good reason ! Sure an unexisting array would not lead every time to an error for the user, but for the maintanability of code I prefer write a little more and get a warning free code.

    I am currently enforcing my own practices using E_STRICT reporting too, it gaves good hint when working with full OOP applications (method overloading without the same parameters, etc.)

  6. You can not handle the following error using userland custom error handler: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING

  7. Yes that’s why we use the tags to catch it

  8. Thanks :) i add captcha for the spammers

  9. Good Job sweety! :wink:

    Keep it up! =)

    muaaaa xoxo

  10. We have done a service for managing a your exceptions online.

    You may want to checkout http://errorapp.com

    https://github.com/rubyrockers/errorapp_notifier-php

    This helps in tracking all exceptions in PHP applications.


Leave a comment

You must be logged in to post a comment.