Error Handling
Understand PHP's traditional error levels, how to control error reporting for development versus production, and why exceptions have largely replaced old-style error handling.
Introduction
Things go wrong in every program: a file might be missing, a variable might be undefined, or a function might be called with the wrong number of arguments. Long before modern exception handling existed, PHP already had a system for reporting these problems — its traditional error levels.
Understanding this older error system still matters, because PHP itself, and many libraries, continue to raise notices, warnings, and fatal errors this way. This lesson covers what those error levels mean, how to control what gets displayed, and how PHP has evolved to favor exceptions for problems your code can actually recover from.
- The difference between notices, warnings, and fatal errors.
- How to control error visibility with error_reporting() and display_errors.
- Why development and production servers should be configured differently.
- How to register a custom error handler with set_error_handler().
- Why silencing errors with @ is discouraged, and how exceptions fit into the picture.
PHP Error Levels
PHP classifies problems into different severity levels. Not every problem stops your script — some are just warnings that something looks off, while others are fatal and halt execution immediately.
| Level | Constant | Meaning |
|---|---|---|
| Notice | E_NOTICE | A minor issue, such as using an undefined variable. Script continues running. |
| Warning | E_WARNING | A more serious issue, such as calling a function with a missing required argument or including a file that does not exist. Script continues running. |
| Fatal Error | E_ERROR | A critical problem, such as calling an undefined function. Script execution stops immediately. |
| Parse Error | E_PARSE | A syntax mistake that prevents PHP from even understanding the script. Script never runs. |
<?php
echo $undefinedVariable;
echo "This line still runs.";Warning: Undefined variable $undefinedVariable in notice-example.php on line 2
This line still runs.Notice that the script kept running after the warning — this is a key difference from fatal errors, which stop execution on the spot.
<?php
echo "Before the call.\n";
undefinedFunction();
echo "This line never runs.";Before the call.
Fatal error: Uncaught Error: Call to undefined function undefinedFunction() in fatal-example.php:3Controlling Error Display
PHP gives you fine-grained control over which error levels get reported, and whether they are shown on the page at all. The error_reporting() function sets which levels are tracked, while the display_errors setting (in php.ini or set at runtime) controls whether they are printed to the output.
<?php
// Report all error types
error_reporting(E_ALL);
// Show errors directly in the page output
ini_set("display_errors", 1);
echo $stillUndefined;Warning: Undefined variable $stillUndefined in error-reporting.php on line 7You can also silence specific levels rather than all of them. For example, reporting everything except notices and deprecation warnings is common in older codebases still transitioning to stricter standards.
<?php
// Report everything except notices and deprecated warnings
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);Development vs Production Settings
Showing detailed errors is helpful while building an application, but dangerous once it is live — error messages can reveal file paths, database structure, or other details useful to attackers. Because of this, development and production servers should be configured very differently.
Development
- error_reporting(E_ALL)
- display_errors = On
- Errors shown directly on the page
- Helps you catch problems immediately
Production
- error_reporting(E_ALL) (still track everything)
- display_errors = Off
- Errors logged to a file, never shown to visitors
- log_errors = On with an error_log path set
<?php
// Typical production-safe configuration
error_reporting(E_ALL);
ini_set("display_errors", 0);
ini_set("log_errors", 1);
ini_set("error_log", "/var/log/php/app-errors.log");Displaying raw PHP errors to visitors can leak file paths, database queries, and internal logic. Always log errors to a file on production servers instead of printing them to the page.
Custom Error Handlers
Instead of relying on PHP's default error output, you can register your own function to handle errors using set_error_handler(). This is useful for logging errors in a custom format or sending alerts when something goes wrong.
<?php
function myErrorHandler($errno, $errstr, $errfile, $errline) {
echo "Custom handler caught: [$errno] $errstr in $errfile on line $errline";
}
set_error_handler("myErrorHandler");
echo $undefinedAgain;Custom handler caught: [2] Undefined variable $undefinedAgain in custom-handler.php on line 8A custom handler receives the error level, message, file, and line number, giving you full control over what happens next — logging it, formatting it nicely, or even converting it into an exception.
The Trouble with @
PHP lets you prefix any expression with the @ operator to suppress errors it produces. While tempting, this is widely considered bad practice.
<?php
$value = @$array["missingKey"]; // no warning shown, even though the key does not exist
var_dump($value);NULL- It hides real problems instead of fixing them, making bugs harder to find later.
- It suppresses ALL errors on that line, not just the one you expected.
- It can silently swallow serious issues, like a failed database connection.
- A better approach is to check conditions explicitly (e.g. isset(), array_key_exists()) before using a value.
Errors vs Exceptions
This traditional error system has been part of PHP since its early days, but modern PHP increasingly favors exceptions for problems that your code can anticipate and recover from — like a failed file open, invalid user input, or a database connection failure.
Notices and warnings are still useful for catching mistakes like typos in variable names, but for recoverable, expected failure conditions, modern PHP code typically throws and catches exceptions instead. The next lesson covers exception handling in depth.
Common Mistakes
- Leaving display_errors turned on in a production environment.
- Overusing @ to silence errors instead of fixing the underlying cause.
- Forgetting to enable log_errors in production, losing visibility into real problems.
- Assuming a warning means the script stopped — only fatal errors halt execution.
Best Practices
- Set error_reporting(E_ALL) everywhere so nothing goes unnoticed, but control visibility separately with display_errors.
- Turn display_errors off and log_errors on for any production deployment.
- Avoid the @ suppression operator — handle the actual condition instead.
- Use set_error_handler() sparingly and only when you need custom logging or reporting behavior.
- Prefer exceptions over relying on old-style errors for conditions your code can meaningfully handle.
Frequently Asked Questions
What is the difference between a warning and a fatal error?
A warning reports a problem but lets the script keep running. A fatal error is severe enough that PHP stops executing the script immediately.
Should display_errors ever be on in production?
No. It can expose sensitive information like file paths and database details to visitors. Use log_errors instead, and review the log file yourself.
Is using @ ever acceptable?
It is rare. Almost every case where @ is used can be replaced with an explicit check, like isset() or a try/catch block, which is clearer and safer.
Do I still need to know about error levels if I use exceptions?
Yes. PHP itself, and many built-in functions and libraries, still raise traditional errors, so understanding both systems is important.
Can I convert traditional errors into exceptions?
Yes, using set_error_handler() you can write a handler that throws an ErrorException, effectively converting old-style errors into exceptions you can catch.
Key Takeaways
- PHP classifies problems into levels: notices and warnings (script continues) versus fatal and parse errors (script stops).
- error_reporting() controls which levels are tracked; display_errors controls whether they are shown on the page.
- Development environments should show errors; production environments should log them instead.
- set_error_handler() lets you register a custom function to process errors your own way.
- The @ suppression operator hides problems rather than fixing them and should be avoided.
- Modern PHP favors exceptions over old-style errors for recoverable problems, covered in the next lesson.
Summary
PHP's traditional error system — notices, warnings, and fatal errors — has existed since the language's earliest days, and understanding it helps you diagnose problems and configure your servers correctly, especially the crucial difference between development and production settings.
Next, you will learn about exception handling, the modern, more structured way PHP lets you catch and respond to problems your code can anticipate and recover from.
- You can identify notices, warnings, and fatal errors.
- You can configure error_reporting() and display_errors for different environments.
- You know how to register a custom error handler.
- You understand why @ is discouraged and how exceptions fit into modern PHP.