The exception mechanism was introduced in version PHP 5 in addition to its new object-oriented model. Just as in Java, C ++, ActionScript 3, or Visual Basic (to name only these programming languages), exceptions to simplify, personalize and organize the management “errors” in a computer program. Here the word “errors” does not mean “bug”, which is an abnormal behavior of the developed application, but “exceptional cases” to treat differently in the program sequence. Let us therefore how the exceptions.
We will introduce at first the native PHP Exception class 5. Then we will study how to throw and catch exceptions in a program. From there we will be able to extend the model to develop Exception derived exceptions and types. Finally, we discuss the concept of event-handling exceptions using the exception handler native php.
We’ll be covering the following topics in this tutorial:
Native Exception class
As we have already explained in previous tutorials OOP, PHP since version 5 has a similar object model to that of Java. To enhance this new engine, the PHP development team has integrated a native Exception class. This very special class allows the developer to streamline the processing of exceptional cases likely to occur during the execution of a program by generating Exception type objects. Ultimately, remember that an exception is nothing more than an object (instance of a class). The following listing shows the code of the Exception class.
Source of the native class Exception Code
<? php class Exception { protected $ message = 'Unknown exception'; // Message of exception protected $ code = 0; // Exception code defined by the user protected $ file; // Source filename of exception protected $ line; // Source line of the exception function __construct (string $ message = NULL, int code = 0); final function getMessage (); // Message of exception final function getCode (); // Exception code final function getFile (); // Source filename final function getLine(); // Line of the source file final function getTrace (); // An array of backtrace () final function getTraceAsString (); // Formatted string trace / * * Replaceable / function __toString (); // Formatted string for display } ?>
We identify very clearly here 4 separate parts that make up this class Exception. The first block of code declares the 4 data members (attributes) of the protected class visibility. Respectively, these attributes record the error message, code, source file in question and the line where the error was generated in the program.
Then comes the declaration of the class constructor takes two optional parameters. The first is the error message and the second error code.
The third part of the body of the class regarding the declaration of 6 accessor methods that can not be redefined by inheritance. This restriction is represented by the final keyword. These methods are respectively used to retrieve the error message, the error code, the source file in question, the line of the error in the file, and the call stack.
Finally, we find the statement of the magic __toString () method that can then be redefined by inheritance. This particular method, when overloaded, to specify how it is decided to represent the current state of the object as a string.
Generate, throw and catch exceptions through the program
Generate an exception
Creating an exception is made by the constructor call of the native Exception class. The code below illustrates this step.
<? php // Create the object Exception $ e = new Exception ('An error \ occurred'); // Display the error message echo $ e-> getMessage (); ?>
Notice the simplicity. The first line create the object of type Exception ($ e) and automatically assigns the error message in the constructor. The second line of
code displays the error message recorded on the standard output.
Note [1]: in software development, programmers have become accustomed to appoint an exception only with tiny letter “e”. This is both a naming convention
and good very widespread practice. However, there are no rules forcing developers to adopt it.
Note[2] : native Exception class is loaded automatically by PHP, so there is no need to resort to any import before you can use it.
Throw an exception through the program
Our previous code allowed us to generate exceptions. As it stands, this script we used strictly for nothing since exception is useful only if it is created when an exceptional event occurs during program execution. For example: a SQL query that fails, not a file to open, a value of an unexpected form field …
When such an event occurs is that something unusual happened. Therefore, the continued implementation of the program should be discontinued and report the incident. This is where actually exceptions. To achieve this, the program should automatically “throw” (remember the vocabulary of OOP) exception. The throw of an exception causes the immediate interruption of the normal program
The throw of an exception through the program is made possible through the keyword “throw”.
Example of throw exception through the program
<? php $ password = 'Toyota'; if ('Liva'! == $ password) { throw new Exception ('Your password is incorrect!'); } // This line will never be executed // Because an exception is thrown to interrupt // The normal program execution echo 'Hello Liva'; ?>
The use of the keyword throw used to stop program execution and redirect except through it. The echo command () on it will never be executed. The $password is not equal to the string ‘Liva’, the exception is automatically generated and then throw.
Note [1]: notice that the exception is generated on the fly. Because it is automatically returned to the program, no need to store the object created in a variable.
Note [2]: exceptions can also be launched from within a class.
This example is far from being usable as is. Indeed, the exception that is thrown to the program here is lost forever. As if we had forgotten to store it in a variable the result returned by a function. We stated at the beginning of the course that the exceptions were intended to treat differently exceptional cases occurring during a program. For this it is necessary to be able to “intercept / catch” the exception generated to apply the proper treatment. This is where the try / catch block.
Intercept / catching an exception generated
As in Java, AS 3, VB, C ++, PHP … has a conditional structure capable of intercepting in flight to allow exceptions to apply special treatment. So it blocks try {} catch () {}. This particular structure is as follows:
Conditional structure try {} catch () {} <? php try { // List of actions to call // These actions can potentially // Throw exceptions through the program } catch (Exception $e) { // Block special actions when // Type of exception is thrown $e } ?>
The try block “try” to run the script from the first two braces. If an exception is thrown in this block, it is immediately “catch” in the catch block () and specific treatments are executed instead.
In practical terms this gives the following list with our previous example:
Intercept example of an exception
<? php try { $ password = 'Toyota'; if ('Liva'! == $ password) { throw new Exception ('Your password is incorrect!'); } echo 'Hello Liva'; } catch (Exception $ e) { echo 'L \' Next error was generated: "\ n";. echo $ e-> getMessage (); } ?>
By running this code, we discover that this is the catch block of code () was executed because the exception thrown in the try {} block was intercepted in flight.
Note [1]: when an exception is thrown, it goes back into the program and is intercepted by the first block try {} catch () {} encompassing she meets. If no try {} catch () {} block surrounding the only exception, the object will be lost and execution of the interrupted program.
Note [2]: we will see later in this tutorial we can apply multiple catch () block in the try {} block to identify each type of potentially generated exception.
Of course, it is possible to nest blocks try {} catch () {} as it is naturally possible to nest the if block (). Our example may be improved as follows:
Easy-block try {} catch () {} nested <? php $ login = 'Toyota'; $ password = 'Liva'; try { if ('Hello'! == $ login) { throw new Exception ('Your login is incorrect!'); } try { if ('Liva'! == $ password) { throw new Exception ('Your password is incorrect!'); } echo 'Hello Liva'; } catch (Exception $ e) { echo 'L \' Next error was generated: "\ n";. echo $ e-> getMessage (); } } catch (Exception $ e) { echo 'L \' Next error was generated: "\ n";. echo $ e-> getMessage (); } ?>
In this example, the value of the login is first tested. As the value of the login is incorrect, an exception is thrown through the program, and this is the catch block () Lowest who intercepts and runs the associated treatment. If now we fill correctly the variable $ login, then the first try block and then passed except the second try block is started. The latter is then caught in the catch block () associated to execute the proper treatment of error.
Finally, we will study a PHP native mechanism to centralize and unify the treatment of uncaught exceptions in a callback that is called automatically by the exception handler.
Derive the Exception class and create custom exceptions
Principle of creating custom classes
This part of the tutorial is undoubtedly the most trivial. It explains how to derive the Exception class (via the concept of inheritance OOP) to then generate custom exceptions. Indeed, as a class = a type, it is possible to create new classes that inherit properties and methods of the Exception class.
What are the advantages to create derived classes? The reason is simple. Have several types of exceptions allows firstly to distinguish more easily. Distinguishing each type of error, we can apply appropriate treatments differently. Finally, the derivation of the Exception class allows the developer to override the object by adding additional properties and methods. The code below shows the simplest to develop a new custom exception class manner.
Principle of creating a subclass of Exception
<? php / ** * File MyChildException.php * / class MyChildException extends Exception { public function __construct ($ message = NULL, $ code = 0) { parent :: __ construct ($ message, $ code); } } ?>
First the name of the new class is declared (MyChildException) and the parent class (Exception) it derives and which it inherits properties and methods. It is through the extends keyword that inheritance occurs.
Then we redefine the constructor method of the parent class Exception. When the constructor of the class will be called MySuperException, it will automatically call the constructor of the parent class. This will effectively create a MySuperException type object type Exception but also by inheritance.
When redefines the parent constructor, so you obviously think recover at least its parameters.
Examples of custom exceptions classes
Now developing as an example two custom classes to handle exceptions related files. The first class to control the non-existence of a file on a server while the second will generate errors indicating that the file is not writable. Add more to each of these two classes, a new attribute storing the date on which the error occurred and an accessor to retrieve this value. So we get:
FileNotFoundException classes and FileNotWriteableException
<? php / ** * File FileNotFoundException.php * / class FileNotFoundException extends Exception { protected $ timestamp; public function __construct ($ message = NULL, $ code = 0) { parent :: __ construct ($ message, $ code); $ this-> timestamp = time (); } public function getTimestamp () { return $ this-> timestamp; } } / ** * File FileNotWriteableException.php * / class FileNotWriteableException extends Exception { protected $ timestamp; public function __construct ($ message = NULL, $ code = 0) { parent :: __ construct ($ message, $ code); $ this-> timestamp = time (); } public function getTimestamp () { return $ this-> timestamp; } } ?>
Take advantage immediately of the legacy to derive the two classes in the same class and FileException that will contain the attribute and the common methodology. This new class, meanwhile, drift course the native Exception class.
Error handling classes related files
<? php / ** * File FileException.php * / class FileException extends Exception { protected $ timestamp; public function __construct ($ message = NULL, $ code = 0) { parent :: __ construct ($ message, $ code); $ this-> timestamp = time (); } public function getTimestamp () { return $ this-> timestamp; } } / ** * File FileNotFoundException.php * / class FileNotFoundException extends FileException { public function __construct ($ message = NULL, $ code = 0) { parent :: __ construct ($ message, $ code); $ this-> timestamp = time (); } } / ** * File FileNotWriteableException.php * / class FileNotWriteableException extends FileException { public function __construct ($ message = NULL, $ code = 0) { parent :: __ construct ($ message, $ code); $ this-> timestamp = time (); } } ?>
The following example shows how to retrieve each type of exception with several catch blocks () associated with the same try {} block . With these catch blocks () online and different types of exceptions, then it is very easy to recognize the error and therefore run lifted the most suitable treatments.
Example of using the 3 file error handling classes
<? php // Import the previous 3 classes require_once (dirname (__ FILE __) '/ FileException.php.'); require_once (dirname (__ FILE __) '/ FileNotFoundException.php.'); require_once (dirname (__ FILE __) '/ FileNotWriteableException.php.'); // Variables $ file = '/var/www/projet/toyota.txt'; try { // Does the file exist? if (! file_exists ($ file)) { throw new FileNotFoundException (.. 'The file' $ file 'does not exist'); } // Is the file writable? if (! is_writeable ($ file)) { throw new FileNotWriteableException ('The file' $ file 'don \' t have the rights of \ 'writing'..); } // Open Did you file in write mode? if (! ($ fp =fopen ($ file, 'w'))) { throw new FileException ('.. $ file' '\' s opening of the file failed '); } // I write in my file fwrite ($ fp, "Hey Emacs \ n"); // Then I close my file fclose ($ fp); } catch (FileNotFoundException $ e) { // I create the file } catch (FileNotWriteableException $ e) { // I change the file rights } catch (FileException $ e) { // I quit all exit ($ e-> getMessage ()); } catch (Exception $ e) { // I quit all exit ($ e-> getMessage ()); } ?>
You notice here the four catch() blocks line to intercept the three types of potentially disposable exceptions from the try() block. Specifying the type of exception caught in the catch() block , we know what kind of error we are dealing. Is it any clearer and maintainable now?
Note: It is important to preserve the order of the catch blocks (), that is to say to the first catch block () indicating the accuracy error. Therefore, the Exception class, the most general, is due to arrive in the last catch block (). If the catch block () of typeException had been placed before the other, then all exceptions (any confused) have been raised therein. Indeed, a FileNotFoundException exception of type is also inherited a FileException type of exception and therefore also uneexception type Exception.
Centralize the handling of uncaught errors
Presentation of the automatic interception mechanism exceptions
So far we know that the easiest way to catch a thrown exception is to use the blocks try {} catch () {}. Remember the very first example, the exception generated was not catchable so she was necessarily lost forever.
Launching such an exception through the program
<? php $ password = 'Toyota'; if ('Lava'! == $ password) { throw new Exception ('Your password is incorrect!'); } // This line will never be executed // Because an exception is thrown to interrupt // The normal program execution echo 'Hello Lava'; ?>
Thankfully PHP has a mechanism to automatically capture all exceptions that are started but not surrounded by blocks try {} catch () {} as is the case in the listing above. it is the exception handler.
The exception handler when he catches an exception, completely interrupts the execution of the program and calls a custom callback function that will do the appropriate treatment of these lost exceptions. The following code illustrates its implementation.
Implementation of automatic interception mechanism exceptions
<? php / ** * A callback function called by the exception handler automatically * *param Exception $e launched an exception and lost in the program *return Void * / function ExceptionProcessing(Exception $ e) { echo 'An orphan exception was caught:'; echo $ e-> getMessage (), "\ n"; exit; } / ** * Saving the callback function in the exception handler PHP * / set_exception_handler ('ExceptionProcessing'); // Exception of Example lost generation $ password = 'Toyota'; if ('Liva'! == $ password) { throw new Exception ('Your password is incorrect!'); } // This line will never be executed // Because an exception is thrown to interrupt // The normal program execution echo 'Hello Liva'; ?>
Some implications are necessary because the principle is not so simple to understand. First, we declare the callback function that will personalize the treatment of orphan intercepted exceptions. This is a custom function that takes a single parameter. This setting is other than an Exception object type (or types derived from Exception). The body of the function performs the special treatment for orphan exceptions. Here we just Let’s display an error message, followed by the exception message. Can we stop all strictly following the PHP program. We could for example automatically redirected the user to a type 500 error page using the header () function.
Note: PHP 5, all objects are automatically passed by reference (pointer) as a function parameter. It is therefore not necessary to prefix the symbol & in the parameter list of the signature.
The second part of this list concerns the registration of the name of this function as default exception handler to call automatically capturing an orphan exception. Just simply call set_exception_handler () PHP function, and to indicate a parameter the name of the ExceptionProcessing () function. PHP then takes over in place of the developer.
Note: PHP interpreter PHP code by reading from top to bottom, so you must always declare the callback function to call before set_exception_handler ().
The last part shows the sample code that generates a non-catchable exception. When the exception is thrown, PHP automatically calls the callback function parameter passing in the orphan except newly generated. The following is achieved on the standard output:
An orphan exception was caught: Your password is incorrect!
The mechanism, although not easy to understand at first glance, appears to be very simple to implement and efficient to manage unexpected exceptional cases. With this tool, developers can write a complete function for easy debugging by displaying eg whole context of execution of the program: global variables, files involved, call stack functions …
Adverse side effects with set_exception_handler
Attention using set_exception_handler () should be used with caution because it can lead to effects particularly troublesome edges if poorly controlled. While the body of the callback function calls other functions or methods which could throw exceptions, the exception handler will be asked repeatedly. It is the infinite loop !!! We must therefore ensure that the body of the callback function does not perform treatments that can generate uncontrolled exceptions.