PHP Exception Handling


Exceptions are used to change the normal flow of a script when a specified error occurs.


What is an Exception

PHP 5 provides a new object-oriented error handling method.

Exception handling is used to change the normal flow of a script when a specified error (exception) condition occurs. This condition is called an exception.

When an exception is triggered, the following usually happens:

  • The current code state is saved
  • Code execution is switched to a predefined (custom) exception handler function
  • Depending on the situation, the handler may resume code execution from the saved code state, terminate script execution, or continue the script from another location in the code

We will show different error handling methods:

  • Basic Use of Exceptions
  • Creating a Custom Exception Handler
  • Multiple Exceptions
  • Rethrowing Exceptions
  • Setting the Top Level Exception Handler

Note:Exceptions should only be used in error situations, and should not be used to jump to another location in the code at a specified point.


Basic Use of Exceptions

When an exception is thrown, the code after it will not continue to execute, and PHP will try to find a matching "catch" block.

If the exception is not caught, and set_exception_handler() is not used for corresponding handling, then a serious error (fatal error) will occur, and an error message of "Uncaught Exception" will be output.

Let's try to throw an exception without catching it:

<?php //Create a function with exception handling function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; } //Trigger an exception checkNum(2); ?>

The above code will get an error similar to this:

Fatal error: Uncaught exception 'Exception' with message 'Value must be 1 or below' in /www/example/test/test.php:7 Stack trace: #0 /www/example/test/test.php(13): checkNum(2) #1 {main} thrown in /www/example/test/test.php on line 7

Try, throw and catch

To avoid the error that appeared in the example above, we need to create appropriate code to handle exceptions.

Appropriate exception handling code should include:

  1. Try - The function using the exception should be inside a "try" block. If no exception is triggered, the code will continue execution as usual. But if an exception is triggered, an exception is thrown.
  2. Throw - specifies how to trigger an exception. Every "throw" must correspond to at least one "catch".
  3. Catch - The "catch" block catches the exception and creates an object containing exception information.

Let's trigger an exception:

<?php //Create a function with exception handling function checkNum($number) { if($number>1) { throw new Exception("The variable value must be less than or equal to 1"); } return true; } //Trigger an exception in the try block try { checkNum(2); //If an exception is thrown, the following text will not be output echo 'If this content is output, it means the $number variable'; } //Catch the exception catch(Exception $e) { echo 'Message: ' .$e->getMessage(); } ?>

The above code will get an error similar to this:

Message: 变量值必须小于等于 1

Example explanation:

The code above threw an exception and caught it:

  1. Create a checkNum() function. It checks whether the number is greater than 1. If so, it throws an exception.
  2. Call the checkNum() function in the "try" block.
  3. The exception in the checkNum() function is thrown.
  4. The "catch" block receives the exception and creates an object containing exception information ($e).
  5. By calling $e->getMessage() on this exception object, output the error message from this exception.

However, to follow the principle that "every throw must correspond to a catch", you can set a top-level exception handler to handle missed errors.


Creating a Custom Exception Class

Creating a custom exception handler is very simple. We simply create a special class whose functions can be called when an exception occurs in PHP. This class must be an extension of the exception class.

This custom customException class inherits all properties of PHP's exception class, and you can add custom functions to it.

Let's start creating the customException class:

<?php class customException extends Exception { public function errorMessage() { //Error message $errorMsg = 'Error line number'.$this->getLine().' in '.$this->getFile() .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address'; return $errorMsg; } } $email = "someone@example...com"; try { //Check e-mail if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //If it is an invalid e-mail address, throw an exception throw new customException($email); } } catch (customException $e) { //display custom message echo $e->errorMessage(); } ?>

This new class is a copy of the old exception class, plus the errorMessage() function. Because it is a copy of the old class, it inherits properties and methods from the old class, and we can use methods of the exception class, such as getLine(), getFile(), and getMessage().

Example explanation:

The code above threw an exception and caught it with a custom exception class:

  1. The customException() class is created as an extension of the old exception class. In this way, it inherits all properties and methods of the old exception class.
  2. Create the errorMessage() function. If the e-mail address is invalid, this function returns an error message.
  3. Set the $email variable to an invalid e-mail address string.
  4. Execute the "try" block, and because the e-mail address is invalid, an exception is thrown.
  5. The "catch" block catches the exception and displays the error message.

Multiple Exceptions

Multiple exceptions can be used for a script to detect multiple situations.

You can use multiple if..else blocks, or a switch block, or nest multiple exceptions. These exceptions can use different exception classes and return different error messages:

<?php class customException extends Exception { public function errorMessage() { //Error message $errorMsg = 'Error line number'.$this->getLine().' in '.$this->getFile() .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address'; return $errorMsg; } } $email = "someone@example.com"; try { //Check e-mail if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //If it is an invalid e-mail address, throw an exception throw new customException($email); } //Check whether "example" is in the e-mail address if(strpos($email, "example") !== FALSE) { throw new Exception("$emailIs an example e-mail"); } } catch (customException $e) { echo $e->errorMessage(); } catch(Exception $e) { echo $e->getMessage(); } ?>

Example explanation:

The code above tests two conditions, and if either condition is not met, an exception is thrown:

  1. The customException() class is created as an extension of the old exception class. In this way, it inherits all properties and methods of the old exception class.
  2. Create the errorMessage() function. If the e-mail address is invalid, this function returns an error message.
  3. Set the $email variable to a string that is a valid e-mail address but contains the string "example".
  4. Execute the "try" block; under the first condition, no exception is thrown.
  5. Because the e-mail contains the string "example", the second condition triggers an exception.
  6. The "catch" block catches the exception and displays an appropriate error message.

If the customException class throws an exception, but customException is not caught, and only the base exception is caught, then the exception is handled there.


Rethrowing Exceptions

Sometimes, when an exception is thrown, you may wish to handle it differently from the standard way. You can rethrow the exception in a "catch" block.

Scripts should hide system errors from users. System errors may be important to programmers, but users are not interested in them. To make it easier for users, you can rethrow an exception with a user-friendly message:

<?php class customException extends Exception { public function errorMessage() { //Error message $errorMsg = $this->getMessage().'is not a valid E-Mail address.'; return $errorMsg; } } $email = "someone@example.com"; try { try { //Check whether "example" is in the e-mail address if(strpos($email, "example") !== FALSE) { //If it is an invalid e-mail address, throw an exception throw new Exception($email); } } catch(Exception $e) { //Rethrow the exception throw new customException($email); } } catch (customException $e) { //Display custom message echo $e->errorMessage(); } ?>

Example explanation:

The code above checks whether the email address contains the string "example". If it does, the exception is rethrown:

  1. The customException() class is created as an extension of the old exception class. This way it inherits all the properties and methods of the old exception class.
  2. Create the errorMessage() function. If the e-mail address is not valid, this function returns an error message.
  3. Set the $email variable to a string that is a valid e-mail address but contains the string "example".
  4. The "try" block contains another "try" block, so that an exception can be thrown again.
  5. Because the e-mail contains the string "example", the exception is triggered.
  6. The "catch" block catches the exception and re-throws "customException".
  7. The "customException" is caught, and an error message is displayed.

If the exception is not caught in the current "try" block, it will look for a catch block at a higher level.


Setting the Top Level Exception Handler

The set_exception_handler() function can set a user-defined function that handles all uncaught exceptions.

<?php function myException($exception) { echo "<b>Exception:</b> " , $exception->getMessage(); } set_exception_handler('myException'); throw new Exception('Uncaught Exception occurred'); ?>

The output of the above code is as follows:

Exception: Uncaught Exception occurred

In the above code, there is no "catch" block; instead, the top-level exception handler is triggered. This function should be used to catch all exceptions that are not caught.


Rules for Exceptions

  • Code that requires exception handling should be placed inside a try block to catch potential exceptions.
  • Every try or throw block must have at least one corresponding catch block.
  • Using multiple catch blocks can catch different kinds of exceptions.
  • An exception can be thrown (re-thrown) in a catch block within a try block.

In short: if an exception is thrown, it must be caught.

Other extensions