Exception Handling

General

An exception is some unusual condition in that it is outside the ordinary expected behavior. Examples include dealing with situations in which a critical resource is needed, but is unavailable, and detecting an out-of-range value for some computation. As such, exceptions require special handling. This chapter describes how exceptions can be created and handled.

Whenever some exceptional condition is detected at runtime, an exception is thrown. A designated exception handler can catch the thrown exception and service it. Among other things, the handler might recover from the situation completely (allowing the script to continue execution), it might perform some recovery and then throw an exception to get further help, or it might perform some cleanup action and terminate the script. Exceptions may be thrown on behalf of the Engine or by explicit code source code in the script.

Exception handling involves the use of the following keywords:

  • try, which allows a try-block of code containing one or more possible exception generations, to be tried.
  • catch, which defines a handler for a specific type of exception thrown from the corresponding try-block or from some function it calls.
  • finally, which allows the finally-block of a try-block to be executed (to perform some cleanup, for example), whether or not an exception occurred within that try-block.
  • throw, which generates an exception of a given type, from a place called a throw point.

When an exception is thrown, an exception object of type Exception, or of a subclass of that type, is created and made available to the first catch-handler that can catch it. Among other things, the exception object contains an exception message and an exception code, both of which can be used by a handler to determine how to handle the situation.

PHP errors also can be translated to exceptions via the class ErrorException (which is not part of this specification).

Class Exception

Class Exception is the base class of all exception types. This class is defined, as follows:

class Exception implements Throwable
{
  protected $message = 'Unknown exception';
  protected $code = 0;
  protected $file;
  protected $line;

  public function __construct($message = "", $code = 0,
               Throwable $previous = NULL);

  final private function __clone();
}

For information about exception trace-back and nested exceptions, see tracing exceptions.

For information about the base interface, see Throwable. Note that the methods from Throwable are implemented as final in the Exception class, which means the extending class can not override them.

The class members are defined below:

NamePurpose
$codeint; the exception code (as provided by the constructor)
$filestring; the name of the script where the exception was generated
$lineint; the source line number in the script where the exception was generated
$messagestring; the exception message (as provided by the constructor)
__constructTakes three (optional) arguments – string: the exception message (defaults to “”), int: the exception code (defaults to 0), and Exception: the previous exception in the chain (defaults to NULL)
__clonePresent to inhibit the cloning of exception objects

Tracing Exceptions

When an exception is caught, the get* functions in class Exception provide useful information. If one or more nested function calls were involved to get to the place where the exception was generated, a record of those calls is also retained, and made available by getTrace, through what is referred to as the *function stack trace*, or simply, trace`.

Let’s refer to the top level of a script as function-level 0. Function-level 1 is inside any function called from function-level 0. Function-level 2 is inside any function called from function-level 1, and so on. The method getTrace returns an array. Exceptions generated at function-level 0 involve no function call, in which case, the array returned by getTrace is empty.

Each element of the array returned by getTrace provides information about a given function level. Let us call this array trace-array and the number of elements in this array call-level. The key for each of trace-array’s elements has type int, and ranges from 0 to call-level - 1. For example, when a top-level script calls function f1, which calls function f2, which calls function f3, which then generates an exception, there are four function levels, 0–3, and there are three lots of trace information, one per call level. That is, trace-array contains three elements, and they each correspond to the reverse order of the function calls. For example, trace-array[0] is for the call to function f3, trace-array[1] is for the call to function f2, and trace-array[2] is for the call to function f1.

Each element in trace-array is itself an array that contains elements with the following key/value pairs:

KeyValue TypeValue
“args”arrayThe set of arguments passed to the function
“class”stringThe name of the function’s parent class
“file”stringThe name of the script where the function was called
“function”stringThe name of the function or class method
“line”intThe line number in the source where the function was called
“object”objectThe current object
“type”stringType of call; -> for an instance method call, :: for a static method call, for ordinary function call, empty string("") is returned.

The key args has a value that is yet another array, which we shall call argument-array. That array contains a set of values that corresponds directly to the set of values passed as arguments to the corresponding function. Regarding element order, argument-array[0] corresponds to the left-most argument, argument-array[1] corresponds to the next argument to the right, and so on.

Note that only the actual arguments passed to the function are reported. Consider the case in which a function has a default argument value defined for a parameter. If that function is called without an argument for the parameter having the default value, no corresponding argument exists in the argument array. Only arguments present at the function-call site have their values recorded in array-argument.

See also, library functions debug_backtrace and debug_print_backtrace.

User-Defined Exception Classes

An exception class is defined simply by having it extend class Exception. However, as that class’s __clone method is declared final, exception objects cannot be cloned.

When an exception class is defined, typically, its constructors call the parent class’ constructor as their first operation to ensure the base-class part of the new object is initialized appropriately. They often also provide an augmented implementation of __toString().