I am a programmer and architect (the kind that writes code) with a focus on testing and open source; I maintain the PHPUnit_Selenium project. I believe programming is one of the hardest and most beautiful jobs in the world. Giorgio is a DZone MVB and is not an employee of DZone and has posted 638 posts at DZone. You can read more from them at their website. View Full User Profile

What you must know about PHP errors to avoid scratching your forehead when something goes wrong

03.03.2011
| 10972 views |
  • submit to reddit
While pure object-oriented languages produces mainly exceptions to signal an error, PHP started out as procedural and so it has a wide range of errors that can be raised along with exceptions.

What is the difference between the two?

Exceptions are objects which can be managed and caught with try/catch blocks. You can create your own exception classes, with custom arguments and methods. They're really objects with special additional functionalities and you should definitely manage your error with them in PHP 5 and higher.

Errors are accompanied by a message like exceptions, but they are managed by calling an error handler function (which may be custom) from the point when they occur. PHP and its native functions generate mostly errors and not exceptions. PDO and the SPL are the exceptions (what a pun) since they have an object-oriented Api which comprehends also exception classes.

Exceptions always bubble up until they are caught; errors are instead passed to the current error handler, whose job is to decide what to do with them. With non-severe errors, printing them in bold and go on with execution is the default behavior.

Understanding exceptions and their usage is a key topic of transitioning to object-oriented PHP, but is out of the scope of this article. Here we will treat errors, since you'll always have to deal with PHP native functions even if your code is so good it only throws exception of your custom hierarchy: when you omit a {, an error is generated, not an exception. When a file passed to include() is missing, again an error is generated, not an exception.

Most of the time unhandled errors are the result of a programming error: if you get an error to be generated, probably something is already gone really wrong and you shouldn't ignore them.

Translation into exceptions

However dealing with errors in an object-oriented way is very difficult: you can't catch them. Thus PHPUnit translates errors into exceptions by defining a custom error handler that throws PHPUnit_Frameworks_Error_Notice or PHPUnit_Framework_Error_Warning in case of manageable errors.

PHPUnit will also signal you with an E in the test base in case of an error, while the F is reserved for particular exceptions that designate assertion failures.

Nothing stops you from doing the same: by defining your error handler, you can translate the errors of missing files in include() into an exception you can catch. The question is: shall you? Often a missing file, when containing for example the source code of a class, will only result in a more seriour error like a Fatl one when the script is allowed to continue.

Main error types

These are the main types of error, which were present in the language from before PHP 4. The majority of the times during development, you'll only see one of this four error types.

  • E_NOTICE: a non critical error, like accessing an initialized variable. PHP is very forgiving and will allow the script to continue in production environments.
  • E_WARNING: a more serious error, like passing a non-Traversable to foreach(), or including a missing file.
  • E_PARSE: a syntax error, like a missing } or using a reserved keyword for naming a class. The script won't run at all as these errors are raised at compile (to pcodes) time.
  • E_ERROR: also known as Fatal Errors, they are unrecoverable even by the error handler. Calling a method on null, or calling an undefined function, or creating an object of a non-existing class would result in a Fatal Error, which will terminate the script abruptly (even if it is a test suite!)

There are many other types of errors, but they are rarer to encounter. The full list is on the PHP manual.

From the list, some interesting special errors should be mentioned:

  • E_STRICT: infringement of strict standards, which from PHP 5.3 it is in the default. If you call a non-static method statically (by Class::method()), you will get this error. Enabling strict standard can help you improve your code quality.
  • E_RECOVERABLE_ERROR: a catchable version of Fatal Error, such as trying to convert an object without __toString() into a string. It can be managed by error handlers, while Fatal Errors and of course Parse Errors can't (they leave the interpreter in an unstable state and cause an immediate exit()).

php.ini directives

There are two directives which are very interesting for managing errors.

The first is error_reporting, which prescribes to report some types of errors while masking other. Typically this value varies between production environments (don't show anything to the end user as it won't understand anyway) and development environments (show me everything as I want to eliminate all errors before shipping.)

In fact, in development I always set error_reporting to E_ALL. Anything else is so '90s.

display_errors has also to be set to On for the errors to be printed. When you get a blank page instead of the expected result, check this directive.

PHP functions

error_reporting() allows you to set which errors to report and override the error_reporting in php.ini, again by using E_ALL and other constants. Note that some errors, like E_PARSE, are detected at compile time and so won't be influenced by this function.

set_error_handler() allows you to define your own function to manage errors, which can then delegate to PHP default handler or completely override it.

Take-home points

Errors are a tricky part of PHP, but knowing how to read them will speed up your development. In your code, always define exceptions, which are much more versatile, but be prepared to manage errors thrown by PHP itself. Most of the time, they're just programming errors like a typo in a variable name or a missing semicolon. However, you should know how to define custom error handlers in case you're forced to deal with runtime errors like a problem with a socket or a database connection.

Published at DZone with permission of Giorgio Sironi, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Ferenc Kovacs replied on Thu, 2011/03/03 - 12:47pm

Fatl should be fatal(typo).

 you should have mentioned the meaning of error_reporting(0), and error_reporting(-1);

 tell the readers that in production one should only log errors not display them (at least not with detailed information).

 you can catch and handle fatal errors though (either via register_shutdown_function or ob_start callback), thought you cannot continue the execution, or throw any exceptions (no stack frame).

 I have a little php class for error handling, I would appreciate any feedback (or contribution. :P):

https://github.com/Tyrael/php-error-handler

 Tyrael

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.