In-depth exploration of PHP 5.0 Exception Handling Mechanism

Source: Internet
Author: User
Tags php basics php source code

Introduction: This is a detailed page for in-depth exploration of the PHP 5.0 Exception Handling Mechanism. It introduces PHP, related knowledge, skills, experience, and some PHP source code.

Class = 'pingjiaf' frameborder = '0' src = 'HTTP: // biancheng.dnbc?info/pingjia.php? Id = 324026 'rolling = 'no'>
This article is intended to learn about the PhP5 Exception Handling MechanismProgramMember. To read this article, you must have a certain degree of object-oriented programming and PHP basics.

The following member methods are required for the PHP 5 built-in exception classes:

_ Construct () The constructor requires an error message and an optional integer error mark as a parameter.
Getmessage () Get error information
Getcode () ErrorCode
GetFile () Abnormal File
Getline () Number of abnormal rows
Gettrace () Tracks the route transmitted in each step of an exception, saves it to an array, and returns this array.
Gettraceasstring () The function is the same as gettrace (), but the elements in the array can be converted into strings and output in a certain format.

It can be seen that the structure of the exception class is similar to that of pear_error. When an error occurs in your script, you can create your exception object:

$ EX = new exception ("cocould not open $ this-> file ");

The constructor of the exception class accepts an error message and an error code.

Use the throw keyword

After an exception object is created, you can return the object, but you should not use it like this. A better way is to use the throw keyword instead. Throw is used to throw an exception:

Throw new exception ("My message", 44 );

Throw suspends the execution of the script and makes the exception object available to the client code.

The getcommandobject () method is improved as follows:

Index_php5.php

<? PHP // PHP 5
Require_once ('COMMAND _ PhP5/command. php ');
Class commandmanager {
Private $ export dir = "pai_php5 ";

Function getcommandobject ($ cmd ){
$ Path = "{$ this-> export dir}/{$ cmd}. php ";
If (! File_exists ($ PATH )){
Throw new exception ("cannot find $ path ");
}
Require_once $ path;
If (! Class_exists ($ cmd )){
Throw new exception ("class $ cmd does not exist ");
}

$ Class = new reflectionclass ($ cmd );
If (! $ Class-> issubclassof (New reflectionclass ('command '))){
Throw new exception ("$ cmd is not a command ");
}
Return new $ cmd ();
}
}
?>

In the code, we use the reflection API of PhP5 to determine whether the given class belongs to the command type. If you execute this script in the wrong path, the following error will be reported:

Fatal error: uncaught exception 'exception' with message 'could not find command/xrealcommand. php' in/home/XYZ/basicexception. php: 10
Stack trace:
#0/home/XYZ/basicexception. php (26 ):
Commandmanager-> getcommandobject ('xrealcommand ')
#1 {main}
Thrown in/home/XYZ/basicexception. php on line 10

By default, a fatal error occurs when an exception is thrown. This means that a security mechanism is built in the abnormal class. Using only one error mark does not support this function. If the error mark fails to be processed, your script will use the error value to continue execution.

Try-catch statement

To further handle exceptions, we need to use the try-catch statement, including the try statement and at least one catch statement. Any code that calls a method that may throw an exception should use the try statement. Catch statements are used to handle exceptions that may be thrown. The following shows how to handle the exception thrown by getcommandobject:

The second half of index_php5.php

<? PHP
// PHP 5
Try {
$ Mgr = new commandmanager ();
$ Cmd = $ Mgr-> getcommandobject ('realcommand ');
$ Cmd-> execute ();
} Catch (exception $ e ){
Print $ e-> getmessage ();
Exit ();
}
?>

We can see that by combining the throw keyword with the try-catch statement, we can avoid the value returned by the error mark "pollution" class method. "Exception" is a built-in PHP type that is different from any other object and will not be confused.

If an exception is thrown, the script in the try statement stops execution and immediately redirects to the script in the catch statement.

If an exception is thrown but not captured, a fatal error occurs.

Handle multiple errors

So far, exception handling seems similar to our traditional practice-checking that the returned error ID or object value is not much different. Let's take commandmanager with greater care and check whether the command directory exists in the constructor.

Index_php5_2.php

<? PHP
// PHP 5
Require_once ('COMMAND _ PhP5/command. php ');
Class commandmanager {
Private $ export dir = "pai_php5 ";

Function _ construct (){
If (! Is_dir ($ this-> includir )){
Throw new exception ("directory error: $ this-> export dir ");
}
}

Function getcommandobject ($ cmd ){
$ Path = "{$ this-> export dir}/{$ cmd}. php ";
If (! File_exists ($ PATH )){
Throw new exception ("cannot find $ path ");
}
Require_once $ path;
If (! Class_exists ($ cmd )){
Throw new exception ("class $ cmd does not exist ");
}

$ Class = new reflectionclass ($ cmd );
If (! $ Class-> issubclassof (New reflectionclass ('command '))){
Throw new exception ("$ cmd is not a command ");
}
Return new $ cmd ();
}
}
?>

There are two possible causes of program errors (_ construct () and getcommandobject ()). However, we do not need to adjust our Customer Code. You can add a lot of content to the try statement and then process it in a unified manner in catch. If the commandmanager object constructor throws an exception, the execution in the try statement is aborted, And the catch statement is called to catch the exception. Similarly, the same is true for getcommandobject. In this way, we have two potential errors at the same time, and a unique statement to handle all the errors. This makes our code look more neat and can meet the error handling requirements. Compared with the traditional PHP error method mentioned above, it is obviously advantageous.

The second half of index_php5_2.php

Note: Although there are two possible errors in the first half of the Code compared with index_php5.php, this code is exactly the same as that in index_php5.php.

<? PHP
// PHP 5
Try {
$ Mgr = new commandmanager (); // potential error
$ Cmd = $ Mgr-> getcommandobject ('realcommand ');
// Another potential error
$ Cmd-> execute ();
} Catch (exception $ e ){
// Handle either error here
Print $ e-> getmessage ();
Exit ();
}
?>

There is another thing we did not mention. How can we identify different types of errors? For example, we may want to use one method to handle errors that cannot find a directory, and another method to handle invalid command classes.

The exception class can accept an optional integer error identifier, which is a method for distinguishing different error types in a catch statement.

Index_php5_3.php

<? PHP
// PHP 5
Require_once ('COMMAND _ PhP5/command. php ');
Class commandmanager {
Private $ export dir = "pai_php5 ";
Const login man_general_error = 1;
Const login man_illegalclass_error = 2;

Function _ construct (){
If (! Is_dir ($ this-> includir )){
Throw new exception ("directory error: $ this-> export dir", self: Export man_general_error );
}
}

Function getcommandobject ($ cmd ){
$ Path = "{$ this-> export dir}/{$ cmd}. php ";
If (! File_exists ($ PATH )){
Throw new exception ("cannot find $ path", self: Login man_illegalclass_error );
}
Require_once $ path;
If (! Class_exists ($ cmd )){
Throw new exception ("class $ cmd does not exist", self: extends man_illegalclass_error );
}

$ Class = new reflectionclass ($ cmd );
If (! $ Class-> issubclassof (New reflectionclass ('command '))){
Throw new exception ("$ cmd is not a command", self: Unknown man_illegalclass_error );
}
Return $ class-> newinstance ();
}
}
?>

By passing the parameters in cmdman_illegalclass_error and cmdman_general_error, we can let the Customer Code differentiate different types of errors and define different processing policies.

Index_php5_3.php

<? PHP // PHP 5
Try {
$ Mgr = new commandmanager ();
$ Cmd = $ Mgr-> getcommandobject ('realcommand ');
$ Cmd-> execute ();
} Catch (exception $ e ){
If ($ e-> getcode () = commandmanager: Using man_general_error ){
// No way of recovering
Die ($ e-> getmessage ());
} Else if ($ e-> getcode () = commandmanager: Your man_illegalclass_error ){
Error_log ($ e-> getmessage ());
Print "attempting recovery \ n ";
// Perhaps attempt to invoke a default command?
}
}
?>

We can also use another method to achieve this effect-from the most fundamental exception class, we can generate a subclass representing different types of exceptions, and then throw and capture them.

Subclass of exception class

There are two reasons for us to assign sub-classes from the exception class:

1. Let the subclass provide custom functions;

2. Identify exceptions of different types;

Let's look at the second example. When using the commandmanager class, we may produce two errors: one is a general error, such as a directory not found, and the other is that the command object cannot be found or generated. In this way, we need to define two types of exceptions for these two errors.

Index_php5_4.php

<? PHP
// PHP 5
Require_once ('COMMAND _ PhP5/command. php ');
Class commandmanagerexception extends exception {}
Class illegalcommandexception extends exception {}

Class commandmanager {
Private $ export dir = "pai_php5 ";

Function _ construct (){
If (! Is_dir ($ this-> includir )){
Throw new commandmanagerexception ("directory error: $ this-> export dir ");
}
}

Function getcommandobject ($ cmd ){
$ Path = "{$ this-> export dir}/{$ cmd}. php ";
If (! File_exists ($ PATH )){
Throw new illegalcommandexception ("cannot find $ path ");
}
Require_once $ path;
If (! Class_exists ($ cmd )){
Throw new illegalcommandexception ("class $ cmd does not exist ");
}

$ Class = new reflectionclass ($ cmd );
If (! $ Class-> issubclassof (New reflectionclass ('command '))){
Throw new illegalcommandexception ("$ cmd is not a command ");
}
Return $ class-> newinstance ();
}
}
?>

If the correct command directory cannot be found in our class, a commandmanagerexception is thrown. If an error occurs when the command object is generated, the getcommandobject () method throws an illegalcommandexception exception. Note that there are multiple causes that may cause the illegalcommandexception exception to be thrown (for example, the file is not found or the correct class is not found in the file ). The first two examples are combined to provide an integer error identification constant for illegalcommandexception to indicate the causes of errors of different types.

Now the commandmanager class has the ability to handle these kinds of errors. We can add new catch statements to match different error types.

The second half of index_php5_4.php

<? PHP // PHP 5
Try {
$ Mgr = new commandmanager ();
$ Cmd = $ Mgr-> getcommandobject ('realcommand ');
$ Cmd-> execute ();
} Catch (commandmanagerexception $ e ){
Die ($ e-> getmessage ());
} Catch (illegalcommandexception $ e ){
Error_log ($ e-> getmessage ());
Print "attempting recovery \ n ";
// Perhaps attempt to invoke a default command?
} Catch (exception $ e ){
Print "unexpected exception \ n ";
Die ($ e-> getmessage ());
}
?>

If a commandmanager object throws a commandmanagerexception, the corresponding catch statement is executed. The parameters of each catch statement are like a matching test. The first matching catch statement will be executed without other catch statements. Therefore, you should write catch statements for specific exceptions first, and catch statements for general exceptions later.

If you write the catch statement as follows:

<? PHP
// PHP 5
Try {
$ Mgr = new commandmanager ();
$ Cmd = $ Mgr-> getcommandobject ('realcommand ');
$ Cmd-> execute ();
} Catch (exception $ e ){
Print "unexpected exception \ n ";
Die ($ e-> getmessage ());
} Catch (commandmanagerexception $ e ){
Die ($ e-> getmessage ());
} Catch (illegalcommandexception $ e ){
Error_log ($ e-> getmessage ());
Print "attempting recovery \ n ";
// Perhaps attempt to invoke a default command?
}
?>

When an exception is thrown, no matter what the exception is, the first catch statement catch (exception $ e) {} will always be executed. This is because all exceptions belong to the exception type, so they always match. This does not achieve our goal of handling specific exceptions.

If you are capturing exceptions of a specific type, it is a good idea to catch exceptions of the exception type in the last catch statement. The last catch statement indicates catch-all to catch all exceptions. Of course, you may not want to handle exceptions immediately. Instead, you want to pass the exception and handle it as appropriate. This is another part of PHP's exception mechanism that needs to be discussed.

Exception transfer or re-throwing

If we have triggered some exceptions that cannot be handled immediately when they occur, there is a good solution-the responsibility for handling exceptions is returned to the code that calls the current method, that is, an exception (rethrowing exception) is thrown again in the catch statement ). This will cause the exception to be passed up the call chain of the method.

Index_php5_5.php

<? PHP
// PHP 5
Class requesthelper {
Private $ request = array ();
Private $ defacmd cmd = 'defaultcmd ';
Private $ response STR;

Function _ construct ($ request_array = NULL ){
If (! Is_array ($ this-> request = $ request_array )){
$ This-> request =$ _ request;
}
}

Function getcommandstring (){
Return ($ this-> response Str? $ This-> response STR: ($ this-> response STR = $ this-> request ['cmd']);
}

Function runcommand (){
$ Commanstr = $ this-> getcommandstring ();
Try {
$ Mgr = new commandmanager ();
$ Cmd = $ Mgr-> getcommandobject ($ response Str );
$ Cmd-> execute ();
} Catch (illegalcommandexception $ e ){
Error_log ($ e-> getmessage ());
If ($ response Str! = $ This-> defaultcmd ){
$ This-> response STR = $ this-> defaultcmd;
$ This-> runcommand ();
} Else {
Throw $ E;
}
} Catch (exception $ e ){
Throw $ E;
}
}
}

$ Helper = new requesthelper (Array (cmd => 'realcommand '));
$ Helper-> runcommand ();
?>

We have used a piece of client code in the requesthelper class. Requesthelper is used to process user-supplied request data. In the constructor, we accept an array for debugging. If this array is not received, the class uses the $ _ Request array. No matter which array is used, it will be allocated to the variable named $ request. The Customer Code informs the command to be executed by giving the CMD element of the request array. The getcommandstring () method tests an attribute named $ struct Str. If it is null, the method assigns the content of the CMD element in $ request to $ response STR and returns the value. If it is not empty, the method returns the value of the $ response STR attribute directly. Through this mechanism, the command string can be overwritten in the requesthelper class.

In the end, all Exception objects except illegalcommandexception will be handed over to a higher class for later processing. The exception is thrown again in the last catch statement.

} Catch (exception $ e ){
Throw $ E;
}

If we catch an illegalcommandexception exception, we first try to call a default command. We can call the runcommand method repeatedly by setting the $ ultcmd cmd attribute to the same value as $ defacmd cmd. If the $ ultstr and $ defacmd cmd strings are already equal and there is nothing we need to do, then the re-throwing exception occurs.

In fact, Zend engine II will automatically throw all unmatched exceptions, so we can omit the last catch statement. This is the last line of commandmanager: getcommandobject:

Return $ class-> newinstance ();

Pay attention to the following two issues:

First, we assume that the commandmanager class constructor does not require parameters. In this article, we do not discuss the situations where parameters are required.

Secondly, we assume that the command class (which is our custom realcommand) can be instantiated. If the constructor is declared as private, this statement throws a reflectionexception object. If the exception is not handled in requesthelper, the exception will be passed to the code that calls requesthelper. If an exception is thrown implicitly, you 'd better explain it in the document or throw it manually-so that other programmers can easily handle possible exceptions when using your code.

Obtain more information about exceptions.

The following code is used to format and output exception information:

Index_php5_6.php

<? PHP
// PHP 5
Class front {
Static function main (){
Try {
$ Helper = new requesthelper (Array (cmd => 'realcommand '));
$ Helper-> runcommand ();
} Catch (exception $ e ){
Print "Print "<H2 >{$ e-> getmessage ()}
({$ E-> getcode ()}) </H2> \ n ";
Print "file: {$ e-> GetFile ()} <br/> \ n ";
Print "line: {$ e-> Getline ()} <br/> \ n ";
Print $ e-> gettraceasstring ();
Die;
}
}
}
Front: Main ();
?>

If your realcommand class cannot be instantiated (for example, you declare its constructor as private) and run the above code, you can get the output as follows:

Reflectionexception access to non-public constructor of class realcommand (0)
File: C: \ myweb \ apache \ htdocs \ php5exception \ index_php5_4.php
Line: 31
#0 C: \ myweb \ apache \ htdocs \ php5exception \ index_php5_5.php (25): commandmanager-> getcommandobject ()

#1 c: \ myweb \ apache \ htdocs \ php5exception \ index_php5_6.php (10): requesthelper-> runcommand ('realcommand ')

#2 c: \ myweb \ apache \ htdocs \ php5exception \ index_php5_6.php (23): Front: Main ()

#3 {main}

You can see that GetFile () and Getline () respectively return the file and number of rows with exceptions. The getstackasstring () method returns the details of the method call that causes an exception at each layer. From #0 to #4, we can clearly see the exception transmission route.

You can also use the gettrace () method to obtain this information. gettrace () returns a multi-dimensional array. The first element contains the location where an exception occurred, and the second element contains the details of the external method call until the call at the highest level. Each element of this array is also an array containing the following key names ):

Key Description
File Abnormal file generation
Line Number of rows in which the exception occurred class method is located
Function Functions/methods that generate exceptions
Class Class of the called Method
Type Call type: 'indicates a static class member.
'->' Indicates an instantiated call (an object is instantiated before being called)
ARGs Parameters accepted by class methods

Summary

The exception mechanism provides several key benefits:

(1) By concentrated error handling in catch statements, you can separate error handling from the application process. This also improves the readability of the code and looks pleasant. I usually adopt very strict policies to catch all exceptions and abort script execution. In this way, you can obtain the required elasticity and implement secure and easy-to-use exception management.

(2) throwing an exception transmits the abnormal data stream from the lower layer to the upper layer, that is, the exception is returned to the most suitable place for determining how to handle the exception. This may seem a bit strange, but in actual situations, we often cannot decide how to deal with it immediately when an exception occurs.

(3) The throw/catch provided by the exception mechanism avoids direct return error identifiers. the return value of a method can be determined by your class. When other programmers use your code, they can specify to return a desired form without the need to continuously test it.

More articles on "in-depth exploration of PHP 5.0 Exception Handling Mechanism"

Love J2EE follow Java Michael Jackson video station JSON online tools

Http://biancheng.dnbcw.info/php/324026.html pageno: 15.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.