PHP Error Handling: Never Say die() Again

Introduction
This article is intended for those who are new to PHP error handling. It addresses one of the most common problems that plague beginning PHP developers: effective error visualization.

PHP error handling is well-documented in the online man pages, but the documentation often eludes beginners, who are trying to learn PHP by copying examples they found on the internet. Copying the code without understanding the code is an antipractice, and there are so many bad PHP examples out there, it can sometimes be difficult to find good ones! This article will help you get the most, quickly and easily, out of PHP's basic error handlers. You can get excellent error information, informative and well-targeted, by just following a few simple examples. So stop copying those obsolete internet examples, and instead make a few "teaching examples" for your own library. By the time you've finished this article, you will have some great insights into how to diagnose the most common errors quickly and find good solutions.

What's Covered Here
PHP has unlimited opportunities for errors, but in practice only a few things are needed to get good diagnostics. You need to be able to see the errors in PHP and you need to be able to see the errors in the PHP extensions, like MySQLi. These require some PHP settings, and a little bit of code to call out the errors in the extensions. This article will show how to get PHP to report the errors and how to get the extensions to report their errors, too.

PHP Won't Help You if You Won't Help Yourself!
PHP has a long history of trying to be "easy to use." One of the early strategies for ease of use was, some might say, a bit misguided. That early strategy was to produce as little error information as possible. Many error conditions produced nothing more than a Notice-level message. But the Notice-level messages were suppressed in the standard PHP installation.

This had the unfortunate effect of letting PHP scripts fail silently at run time, or fail silently and intermittently when the script relied on an undefined variable, a condition that could occur because of a typographical error. Today we know better, and many of those early silent failures are accompanied by warnings. But not all of them are warned. You have to tell PHP that you want to know about the errors. You do that with error_reporting() and a few associated settings.

Settings for Development and Deployment
For most PHP applications you want these settings in the development environment. We are telling PHP to report all the errors, write them into the error_log file, and display them in the browser viewport.

See the difference? The deployed environment does not display the errors, but it still logs them.

What happens when there is an error in the deployed application? You will probably get the "white screen of death,"
depending on the exact location of the error. But no matter what appears in the browser viewport, you will still get the error_log information, so you can investigate the error after the fact.

Error Suppression: A Symptom of Bad Error Handling
Perhaps you have seen something like this in a PHP code sample.

To the trained eye, that is scary. See the @ ("at-sign") prepended to the function name? It's the error suppression operator. And it's like dog poop. It is out of place wherever you find it. Here is what one PHP veteran says on the PHP web site.

Error suppression should be avoided if possible as it doesn't just suppress the error that you are trying to stop, but will also suppress errors that you didn't predict would ever occur. This will make debugging a nightmare.

In my experience, there is almost never any justification for using this. So just don't! Instead, write a bit more code to test for the error conditions you expect. And avoid those error conditions.

If you ever find the @ operator in a sample of PHP code, expect to find a prominent explanation in the associated comments. And if you don't find that explanation, you might want to skip over the example. It's likely that the example came from a novice programmer. There may be other errors lurking in the code, too.

Obscure Error Messages: Another Symptom of Bad Error Handling
Poor error handling is a code smell that can be fairly obvious to the trained eye. It is a code smell because it can leave you frustrated as you see your script fail in a way that tells you nothing about the cause or remedy. One common symptom of inadequate error handling may be the white screen of death. Another common symptom is a meaningless message like "Query failed" or "Cannot connect." These are problematic conditions because they don't tell you anything about what went wrong or where it went wrong. Debugging a script without any meaningful message is like poking about in a dark room - you might hit something, but it's hard to know what's in there.

On the other hand, good error handling is like turning on the lights.

The first and most common mistake is using die(). PHP die() is functionally equivalent to exit(), but die() is seen more frequently in PHP code examples. It terminates the script, and optionally produces a message of the user's choice. Here is an example that produces a nearly meaningless error message and terminates the script.

These examples illustrate bad error handling because
1. They terminate the script, even when it may not be necessary;
2. They give no indication of where the failure occurred;
3. They give no indication of why the failure occurred.

When trigger_error() is used with appropriate diagnostic functions, you can get much better information without even trying
1. You don't have to terminate the script unless you want to;
2. You automatically get the path information and line numbers showing where the error occurred;
3. You automatically get an indication of why the failure occurred.

Now that you know about trigger_error() what should you do? Scan your code library for every instance of a call to exit() or die() and make yourself a project to change these to trigger_error() in each and every case that trigger_error() can possibly be used! Some good examples follow.

Digging Deeper - Getting Meaningful Help from PHP Extensions
Almost all PHP functions return some value, and smart programmers know to test these return values. However many of the outdated examples on the internet do not test the return values, but instead blindly use the results, often with potentially disastrous consequences. A particularly common example seems to arise when using the MySQL database extensions. (Note: the MySQL extension has been removed from PHP, but the terrible code examples still litter the internet!)

When you upgrade from MySQL to MySQLi, you've got a great opportunity to upgrade your error handling. Here's that earlier connect example with improved error handling:

A Bonus: Trigger_Error() is Extensible!
All by itself, trigger_error() is a great improvement over die(), but that's not all. Trigger_error() can be used in conjunction with the built-in error handler, or with a user defined function that has been set as the new error handler. It's beyond the scope of this article, but you might want to read about set_error_handler() if you want more advanced functionality. There is also ErrorException, but I have not personally found a good use for it yet.

Finding and Reading the Error Logs
Whether your application is in development or already deployed, the error_log file is a valuable resource. In my PHP installation, the error_log file is only created if an error has occurred. It may be appended to, if there are successive errors. Going through a lot of server directories to look for error_log can be a laborious task, but we can automate it. I use a script like this one to walk through the web directory tree. It finds and displays the error_log files and gives me a push-button link to remove the error_log.

Checking Your PHP Settings
In case you're wondering about what PHP settings are in play, you can find everything by running this little script, shown here in its entirety. It produces a lot of output, but with a browser search you can find the "good stuff." You might try running this and checking the output for "error" to see what your settings are.

Conclusion
An enormous volume of PHP code has been propagated with die() when a more reasonable code set would use trigger_error() instead. This article has shown how to upgrade your code, and why you never want to use die() again.

If you find that this article has been helpful, please click the “thumb’s up” button below. Doing so lets the E-E community know what is valuable for E-E members and provides direction for future articles. Thanks!

Using this article for work? Experts Exchange can benefit your whole team.

Experts Exchange is a tech solutions provider where users receive personalized tech help from vetted certified professionals. These industry professionals also write and publish relevant articles on our site.

Ask questions about what you read

If you have a question about something within an article, you can receive help directly from the article author. Experts Exchange article authors are available to answer questions and further the discussion.