Exceptions
Table of Contents
PHP has an exception model similar to that of other programming languages. An exception can be throw n, and caught (» catch ed») within PHP. Code may be surrounded in a try block, to facilitate the catching of potential exceptions. Each try must have at least one corresponding catch or finally block.
If an exception is thrown and its current function scope has no catch block, the exception will «bubble up» the call stack to the calling function until it finds a matching catch block. All finally blocks it encounters along the way will be executed. If the call stack is unwound all the way to the global scope without encountering a matching catch block, the program will terminate with a fatal error unless a global exception handler has been set.
The thrown object must be an instanceof Throwable . Trying to throw an object that is not will result in a PHP Fatal Error.
As of PHP 8.0.0, the throw keyword is an expression and may be used in any expression context. In prior versions it was a statement and was required to be on its own line.
catch
A catch block defines how to respond to a thrown exception. A catch block defines one or more types of exception or error it can handle, and optionally a variable to which to assign the exception. (The variable was required prior to PHP 8.0.0.) The first catch block a thrown exception or error encounters that matches the type of the thrown object will handle the object.
Multiple catch blocks can be used to catch different classes of exceptions. Normal execution (when no exception is thrown within the try block) will continue after that last catch block defined in sequence. Exceptions can be throw n (or re-thrown) within a catch block. If not, execution will continue after the catch block that was triggered.
When an exception is thrown, code following the statement will not be executed, and PHP will attempt to find the first matching catch block. If an exception is not caught, a PHP Fatal Error will be issued with an » Uncaught Exception . » message, unless a handler has been defined with set_exception_handler() .
As of PHP 7.1.0, a catch block may specify multiple exceptions using the pipe ( | ) character. This is useful for when different exceptions from different class hierarchies are handled the same.
As of PHP 8.0.0, the variable name for a caught exception is optional. If not specified, the catch block will still execute but will not have access to the thrown object.
finally
A finally block may also be specified after or instead of catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.
One notable interaction is between the finally block and a return statement. If a return statement is encountered inside either the try or the catch blocks, the finally block will still be executed. Moreover, the return statement is evaluated when encountered, but the result will be returned after the finally block is executed. Additionally, if the finally block also contains a return statement, the value from the finally block is returned.
Global exception handler
If an exception is allowed to bubble up to the global scope, it may be caught by a global exception handler if set. The set_exception_handler() function can set a function that will be called in place of a catch block if no other block is invoked. The effect is essentially the same as if the entire program were wrapped in a try — catch block with that function as the catch .
Notes
Internal PHP functions mainly use Error reporting, only modern Object-oriented extensions use exceptions. However, errors can be easily translated to exceptions with ErrorException. This technique only works with non-fatal errors, however.
Example #1 Converting error reporting to exceptions
function exceptions_error_handler ( $severity , $message , $filename , $lineno ) <
throw new ErrorException ( $message , 0 , $severity , $filename , $lineno );
>
Examples
Example #2 Throwing an Exception
function inverse ( $x ) <
if (! $x ) <
throw new Exception ( ‘Division by zero.’ );
>
return 1 / $x ;
>
try <
echo inverse ( 5 ) . «\n» ;
echo inverse ( 0 ) . «\n» ;
> catch ( Exception $e ) <
echo ‘Caught exception: ‘ , $e -> getMessage (), «\n» ;
>
// Continue execution
echo «Hello World\n» ;
?>
The above example will output:
Example #3 Exception handling with a finally block
function inverse ( $x ) <
if (! $x ) <
throw new Exception ( ‘Division by zero.’ );
>
return 1 / $x ;
>
try <
echo inverse ( 5 ) . «\n» ;
> catch ( Exception $e ) <
echo ‘Caught exception: ‘ , $e -> getMessage (), «\n» ;
> finally <
echo «First finally.\n» ;
>
try <
echo inverse ( 0 ) . «\n» ;
> catch ( Exception $e ) <
echo ‘Caught exception: ‘ , $e -> getMessage (), «\n» ;
> finally <
echo «Second finally.\n» ;
>
// Continue execution
echo «Hello World\n» ;
?>
The above example will output:
Example #4 Interaction between the finally block and return
function test () <
try <
throw new Exception ( ‘foo’ );
> catch ( Exception $e ) <
return ‘catch’ ;
> finally <
return ‘finally’ ;
>
>
The above example will output:
Example #5 Nested Exception
class Test <
public function testing () <
try <
try <
throw new MyException ( ‘foo!’ );
> catch ( MyException $e ) <
// rethrow it
throw $e ;
>
> catch ( Exception $e ) <
var_dump ( $e -> getMessage ());
>
>
>
$foo = new Test ;
$foo -> testing ();
The above example will output:
Example #6 Multi catch exception handling
class MyOtherException extends Exception
class Test <
public function testing () <
try <
throw new MyException ();
> catch ( MyException | MyOtherException $e ) <
var_dump ( get_class ( $e ));
>
>
>
$foo = new Test ;
$foo -> testing ();
The above example will output:
Example #7 Omitting the caught variable
Only permitted in PHP 8.0.0 and later.
class SpecificException extends Exception <>
function test () <
throw new SpecificException ( ‘Oopsie’ );
>
try <
test ();
> catch ( SpecificException ) <
print «A SpecificException was thrown, but we don’t care about the details.» ;
>
?>
Example #8 Throw as an expression
Only permitted in PHP 8.0.0 and later.
class SpecificException extends Exception <>
function test () <
do_something_risky () or throw new Exception ( ‘It did not work’ );
>
try <
test ();
> catch ( Exception $e ) <
print $e -> getMessage ();
>
?>
User Contributed Notes 13 notes
If you intend on creating a lot of custom exceptions, you may find this code useful. I’ve created an interface and an abstract exception class that ensures that all parts of the built-in Exception class are preserved in child classes. It also properly pushes all information back to the parent constructor ensuring that nothing is lost. This allows you to quickly create new exceptions on the fly. It also overrides the default __toString method with a more thorough one.
interface IException
<
/* Protected methods inherited from Exception class */
public function getMessage (); // Exception message
public function getCode (); // User-defined Exception code
public function getFile (); // Source filename
public function getLine (); // Source line
public function getTrace (); // An array of the backtrace()
public function getTraceAsString (); // Formated string of trace
/* Overrideable methods inherited from Exception class */
public function __toString (); // formated string for display
public function __construct ( $message = null , $code = 0 );
>
abstract class CustomException extends Exception implements IException
<
protected $message = ‘Unknown exception’ ; // Exception message
private $string ; // Unknown
protected $code = 0 ; // User-defined exception code
protected $file ; // Source filename of exception
protected $line ; // Source line of exception
private $trace ; // Unknown
public function __construct ( $message = null , $code = 0 )
<
if (! $message ) <
throw new $this ( ‘Unknown ‘ . get_class ( $this ));
>
parent :: __construct ( $message , $code );
>
public function __toString ()
<
return get_class ( $this ) . » ‘ < $this ->message > ‘ in < $this ->file > ( < $this ->line > )\n»
. » < $this ->getTraceAsString ()> » ;
>
>
?>
Now you can create new exceptions in one line:
class TestException extends CustomException <>
?>
Here’s a test that shows that all information is properly preserved throughout the backtrace.
function exceptionTest ()
<
try <
throw new TestException ();
>
catch ( TestException $e ) <
echo «Caught TestException (‘ < $e ->getMessage ()> ‘)\n < $e >\n» ;
>
catch ( Exception $e ) <
echo «Caught Exception (‘ < $e ->getMessage ()> ‘)\n < $e >\n» ;
>
>
echo » ;
?>
Here’s a sample output:
error_reporting
(PHP 4, PHP 5, PHP 7, PHP 8)
error_reporting — Sets which PHP errors are reported
Description
The error_reporting() function sets the error_reporting directive at runtime. PHP has many levels of errors, using this function sets that level for the duration (runtime) of your script. If the optional error_level is not set, error_reporting() will just return the current error reporting level.
Parameters
The new error_reporting level. It takes on either a bitmask, or named constants. Using named constants is strongly encouraged to ensure compatibility for future versions. As error levels are added, the range of integers increases, so older integer-based error levels will not always behave as expected.
The available error level constants and the actual meanings of these error levels are described in the predefined constants.
Return Values
Returns the old error_reporting level or the current level if no error_level parameter is given.
Changelog
Version | Description |
---|---|
8.0.0 | error_level is nullable now. |
Examples
Example #1 error_reporting() examples
// Turn off all error reporting
error_reporting ( 0 );
// Report simple running errors
error_reporting ( E_ERROR | E_WARNING | E_PARSE );
// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings . )
error_reporting ( E_ERROR | E_WARNING | E_PARSE | E_NOTICE );
// Report all errors except E_NOTICE
error_reporting ( E_ALL &
// Report all PHP errors
error_reporting ( E_ALL );
// Report all PHP errors
error_reporting (- 1 );
// Same as error_reporting(E_ALL);
ini_set ( ‘error_reporting’ , E_ALL );
Notes
Passing in the value -1 will show every possible error, even when new levels and constants are added in future PHP versions. The behavior is equivalent to passing E_ALL constant.
See Also
- The display_errors directive
- The html_errors directive
- The xmlrpc_errors directive
- ini_set() — Sets the value of a configuration option
User Contributed Notes 27 notes
If you just see a blank page instead of an error reporting and you have no server access so you can’t edit php configuration files like php.ini try this:
— create a new file in which you include the faulty script:
( E_ALL );
ini_set ( «display_errors» , 1 );
include( «file_with_errors.php» );
?>
— execute this file instead of the faulty script file
now errors of your faulty script should be reported.
this works fine with me. hope it solves your problem as well!
Under PHP 8.0, error_reporting() does not return 0 when then the code uses a @ character.
= $array [ 20 ]; // error_reporting() returns 0 in php =8
The example of E_ALL ^ E_NOTICE is a ‘bit’ confusing for those of us not wholly conversant with bitwise operators.
If you wish to remove notices from the current level, whatever that unknown level might be, use &
//.
$errorlevel = error_reporting ();
error_reporting ( $errorlevel &
E_NOTICE );
//. code that generates notices
error_reporting ( $errorlevel );
//.
?>
^ is the xor (bit flipping) operator and would actually turn notices *on* if they were previously off (in the error level on its left). It works in the example because E_ALL is guaranteed to have the bit for E_NOTICE set, so when ^ flips that bit, it is in fact turned off. &
(and not) will always turn off the bits specified by the right-hand parameter, whether or not they were on or off.
The error_reporting() function won’t be effective if your display_errors directive in php.ini is set to «Off», regardless of level reporting you set. I had to set
to keep no error reporting as default, but be able to change error reporting level in my scripts.
I’m using PHP 4.3.9 and Apache 2.0.
In php7, what was generally a notice or a deprecated is now a warning : the same level of a mysql error … unacceptable for me.
I do have dozen of old projects and I surely d’ont want to define every variable which I eventually wrote 20y ago.
So two option: let php7 degrade my expensive SSDs writing Gb/hours or implement smthing like server level monitoring ( with auto_[pre-ap]pend_file in php.ini) and turn off E_WARNING
Custom overriding the level of php errors should be super handy and flexible …
This article refers to these two reporting levels:
// Report all PHP errors (see changelog)
error_reporting(E_ALL);
// Report all PHP errors
error_reporting(-1);
What is the difference between those two levels?
Please update this article with a clear explanation of the difference and the possible use cases.
E_NOTICE integer value is 6135
If you want to see all errors in your local environment, you can set your project URL like «foo.com.local» locally and put that in bootstrap file.
if ( substr ( $_SERVER [ ‘SERVER_NAME’ ], — 6 ) == ‘.local’ ) <
ini_set ( ‘display_errors’ , 1 );
ini_set ( ‘error_reporting’ , E_ALL );
// or error_reporting(E_ALL);
>
?>
If you are using the PHP development server, run from the command line via `php -S servername:port`, every single error/notice/warning will be reported in the command line itself, with file name, and line number, and stack trace.
So if you want to keep a log of all the errors even after page reloads (for help in debugging, maybe), running the PHP development server can be useful.
Some E_STRICT errors seem to be thrown during the page’s compilation process. This means they cannot be disabled by dynamically altering the error level at run time within that page.
The work-around for this was to rename the file and replace the original with a error_reporting() call and then a require() call.
Ex, rename index.php to index.inc.php, then re-create index.php as:
( E_STRICT | E_NOTICE ));
require( ‘index.inc.php’ );
?>
That allows you to alter the error reporting prior to the file being compiled.
I discovered this recently when I was given code from another development firm that triggered several E_STRICT errors and I wanted to disable E_STRICT on a per-page basis.
see more information about php 5.3 deprecated errors
I had the problem that if there was an error, php would just give me a blank page. Any error at all forced a blank page instead of any output whatsoever, even though I made sure that I had error_reporting set to E_ALL, display_errors turned on, etc etc. But simply running the file in a different directory allowed it to show errors!
Turns out that the error_log file in the one directory was full (2.0 Gb). I erased the file and now errors are displayed normally. It might also help to turn error logging off.
To expand upon the note by chris at ocproducts dot com. If you prepend @ to error_reporting(), the function will always return 0.
( E_ALL );
var_dump (
error_reporting (), // value of E_ALL,
@ error_reporting () // value is 0
);
?>
this is to show all errors for code that may be run on different versions
for php 5 it shows E_ALL^E_STRICT and for other versions just E_ALL
if anyone sees any problems with it please correct this post
Note that E_NOTICE will warn you about uninitialized variables, but assigning a key/value pair counts as initialization, and will not trigger any error :
( E_ALL );
$foo = $bar ; //notice : $bar uninitialized
$bar [ ‘foo’ ] = ‘hello’ ; // no notice, although $bar itself has never been initialized (with «$bar = array()» for example)
$bar = array( ‘foobar’ => ‘barfoo’ );
$foo = $bar [ ‘foobar’ ] // ok
$foo = $bar [ ‘nope’ ] // notice : no such index
?>
This is very useful to remember when setting error_reporting levels in httpd.conf:
Use the table above or:
( «error_reporting» , E_YOUR_ERROR_LEVEL );
echo ini_get ( «error_reporting» );
?>
To get the appropriate integer for your error-level. Then use:
php_admin_value error_reporting YOUR_INT
I want to share this rather straightforward tip as it is rather annoying for new php users trying to understand why things are not working when the error-level is set to (int) «E_ALL» = 0.
Maybe the PHP-developers should make ie error_reporting(«E_ALL»); output a E_NOTICE informative message about the mistake?
To enable error reporting for *ALL* error messages including every error level (including E_STRICT, E_NOTICE etc.), simply use:
error_reporting() has no effect if you have defined your own error handler with set_error_handler()
[Editor’s Note: This is not quite accurate.
E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR and E_COMPILE_WARNING error levels will be handled as per the error_reporting settings.
All other levels of errors will be passed to the custom error handler defined by set_error_handler().
Zeev Suraski suggests that a simple way to use the defined levels of error reporting with your custom error handlers is to add the following line to the top of your error handling function:
It might be a good idea to include E_COMPILE_ERROR in error_reporting.
If you have a customer error handler that does not output warnings, you may get a white screen of death if a «require» fails.
Example:
( E_ERROR | E_WARNING | E_PARSE );
function myErrorHandler ( $errno , $errstr , $errfile , $errline ) <
// Do something other than output message.
return true ;
>
$old_error_handler = set_error_handler ( «myErrorHandler» );
require «this file does not exist» ;
?>
To prevent this, simply include E_COMPILE_ERROR in the error_reporting.
( E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR );
?>
I always code with E_ALL set.
After a couple of pages of
= (isset( $_POST [ ‘username’ ]) && !empty( $_POST [ ‘username’ ])).
?>
I made this function to make things a little bit quicker. Unset values passed by reference won’t trigger a notice.
function test_ref (& $var , $test_function = » , $negate = false ) <
$stat = true ;
if(!isset( $var )) $stat = false ;
if (!empty( $test_function ) && function_exists ( $test_function )) <
$stat = $test_function ( $var );
$stat = ( $negate ) ? $stat ^ 1 : $stat ;
>
elseif( $test_function == ’empty’ ) <
$stat = empty( $var );
$stat = ( $negate ) ? $stat ^ 1 : $stat ;
>
elseif (! function_exists ( $test_function )) <
$stat = false ;
trigger_error ( » $test_function () is not a valid function» );
>
$stat = ( $stat ) ? true : false ;
return $stat ;
>
$a = » ;
$b = ’15’ ;
test_ref ( $a , ’empty’ , true ); //False
test_ref ( $a , ‘is_int’ ); //False
test_ref ( $a , ‘is_numeric’ ); //False
test_ref ( $b , ’empty’ , true ); //true
test_ref ( $b , ‘is_int’ ); //False
test_ref ( $b , ‘is_numeric’ ); //false
test_ref ( $unset , ‘is_numeric’ ); //false
test_ref ( $b , ‘is_number’ ); //returns false, with an error.
?>
error_reporting() may give unexpected results if the @ error suppression directive is used.
@include ‘config.php’ ;
include ‘foo.bar’ ; // non-existent file
?>
config.php
( 0 );
?>
will throw an error level E_WARNING in relation to the non-existent file (depending of course on your configuration settings). If the suppressor is removed, this works as expected.
Alternatively using ini_set(‘display_errors’, 0) in config.php will achieve the same result. This is contrary to the note above which says that the two instructions are equivalent.
Only display php errors to the developer.
if( $_SERVER [ ‘REMOTE_ADDR’ ]== «00.00.00.00» )
<
ini_set ( ‘display_errors’ , ‘On’ );
>
else
<
ini_set ( ‘display_errors’ , ‘Off’ );
>
?>
Just replace 00.00.00.00 with your ip address.
Creating a Custom Error Handler
set_error_handler(«customError»,E_ALL);
function customError($errno, $errstr)
<
echo «Error: [$errno] $errstr
«;
echo «Ending Script»;
die();
>
In phpinfo() error reporting level display like a bit (such as 4095)
Maybe it is a simply method to understand what a level set on your host
if you are not have access to php.ini file
= ini_get ( ‘error_reporting’ );
while ( $bit > 0 ) <
for( $i = 0 , $n = 0 ; $i $bit ; $i = 1 * pow ( 2 , $n ), $n ++) <
$end = $i ;
>
$res [] = $end ;
$bit = $bit — $end ;
>
?>
In $res you will have all constants of error reporting
$res[]=int(16) // E_CORE_ERROR
$res[]=int(8) // E_NOTICE
.