Methods of exception Handling in PHP

Source: Internet
Author: User
Tags soap spl pear zend framework
This article mainly introduces the method of exception handling in PHP, the interested friend's reference, hope to be helpful to everybody.

Each new feature added to the PHP runtime creates an exponential random number, in such a way that developers can use and even abuse this new feature. However, it was not until a few good and bad use cases emerged that the developers reached a consensus. As these new cases continue to emerge, we can finally discern what is best or worst.

Exception handling in PHP is certainly not a new feature in any way. However, in this article, we will discuss two new features that are based on exception handling in PHP 5.3. The first is a nested exception the second is a set of SPL (now a core extension of the PHP runtime mechanism) that extends the new exception type. With these two new features, you'll find best practices in this book that you'll be looking at in detail.


It is important to note that some of these features already exist in PHP versions less than 5.3, or at least in versions below 5.3. And when this article mentions PHP 5.3, it is not the PHP runtime version that is strictly responsible. Instead, it means that the code base and the project are in PHP 5.3 as the lowest version, but at the same time all the best practices that emerge at the new stage of development. This stage of development highlights a number of "2.0" attempts by specific projects such as the Zend Framework, Symfony, Doctrine and PEAR.

Background

PHP 5.2 has only one exception class Exception. According to the development criteria of Zend framework/pear, this class is the base class for all exception classes in your library. If you create a library called MyCompany, by Zend framework/pear, all code files in the library will start with Mycompany_. If you want to create your own exception base class for the library: mycompany_exception, then use that class to inherit the Exception and then inherit and throw the exception class by the component (component). For example, if you have a component Mycompany_foo, you can create an exception base class mycompany_foo_exception that is used inside the component. These exceptions can be caught by capturing mycompany_foo_exception,mycompany_exception or Exception code. For other code in the library that is used in this component, this is a three-layer exception (or more, depending on how many mycompany_foo_exception subclasses there are), and they can handle these exceptions to their own needs.


In PhP5, the basic exception class already supports nested attributes. What is nesting? Nesting is a capability to catch a special exception, or to capture a new exception object created by referencing the original exception. This will allow the caller property to be reflected on the two exception classes that appear in the more exposed types of overhead libraries, and, of course, on the exception classes that have the original exception behavior.

Why are these features useful? Typically, exceptions that throw their own type by using other code are the most efficient code. The code might be code that uses the adapter pattern to provide a third-party code base that provides some more adaptable functions, or simple code that uses some PHP extensions to throw exceptions.


For example, in component zend_db, it uses the adapter pattern to encapsulate a specific PHP extension to create a database abstraction layer. In one adapter, zend_db encapsulates PDO, and PDO throws its own exception pdoexception, zend_db need to capture these PDO-specific exceptions and have them re-thrown with predictable and type-known zend_db_exception. This gives the developer the assurance that zend_db will always throw zend_db_exception types of exceptions (and therefore can be captured), and they can also access the pdoexception that were thrown at the beginning when needed.

The following example shows how a fictitious database adapter might implement an embedded exception:

Class mycompany_database{/**  * @var PDO Object Setup during construction  */protected $_pdoresource = NULL;   /**  * @throws mycompany_database_exception  * @return int *  /Public Function executeQuery ($sql) {  try { c7/> $numRows = $this->_pdoresource->exec ($sql);  } catch (Pdoexception $e) {   throw new Mycompany_database_exception (' Query was unexecutable ', null, $e);  }  return $numRows; } }

To use an embedded exception, you have to invoke the GetPrevious () method of the caught exception:

$sql and $connectionParameters assumedtry {$db = new mycompany_database (' PDO ', $connectionParams); $db->executeque Ry ($sql);} catch (Mycompany_database_exception $e) {echo ' General Error: '. $e->getmessage (). "\ n"; $pdoException = $e->getprevious (); Echo ' PDO specific error: '. $pdoException->getmessage (). "\ n";}

Most recently implemented PHP extensions have OO (object-oriented) interfaces. Therefore, these APIs tend to throw exceptions instead of terminating the error. PHP can throw an exception in the extension, a few lists include PDO, DOM, Mysqli, Phar, Soap and SQLite.

New feature: New Core exception type

In the development of PHP 5.3, we have shown some interesting new exception types. These exceptions already exist in PHP 5.2.x, but they have not recently been the best practice for "re-evaluating" anomalies, and now they are becoming more compelling. They are applied in the SPL extension and are listed in the manual (here) because these new exception types are part of the PHP core and are part of SPL, they can be used by anyone who runs code in PHP 5.3 (and above). While it may seem less important to write code at the application layer, it becomes more important to use these new exception types when we write or use code libraries


So why is the new exception a normal type? Previously, developers tried to give the exception more meaning by putting more content in the exception message alert. While this is possible, it has several drawbacks. One is that you cannot capture message-based exceptions. This is a problem, if you know that a group of code is the same exception type and different message corresponding to different exceptions, the difficulty of processing will be quite large. For example, an authentication class, in the case of a $auth->authenticate (); It throws an exception of the same type (assuming an exception), but different messages correspond to two specific faults: the cause of the failure is that the authentication server cannot reach but the same exception type does not prompt for a failed authentication message. In this case (note that using an exception may not be the best way to handle the authentication response), this will require parsing the message with a string to handle both of these different situations.

The solution to this problem is obviously to encode the exception in some way, so that it can be more easily queried when it is necessary to discern how to react to the abnormal environment. The first reaction library is the $code property that uses the exception base class. The other is by creating a subclass or a new exception class that can be thrown and can describe its behavior. These two methods have the same obvious disadvantage. Neither of them presents the best example of such a wish. Neither is considered a standard, so every project that attempts to replicate the two solutions will have a small change, forcing the use of this to return to the document to understand the specific solutions that are already in the library that is being created. Now by using the new type method of SPL, also known as the PHP standard library, developers can be in the same way in their projects, and the new best way to reuse these projects has emerged.


The second drawback is that the use of detailed information makes understanding these anomalies difficult for developers who have limited English or English capabilities. This may make it very slow for developers to try to understand the meaning of unusual information. Many developers also write articles about exceptions, as there is no unified, consolidated standard to describe what the exception message describes as a different version of the same number of developers.

So how do I go about using them, using these words to describe the details of a person without a language?

There are now a total of 13 new exception types in SPL. Two of these can be considered base classes: logical exceptions and run-time exceptions, both of which inherit the PHP exception class. The rest of the methods can logically be split into 3 groups: Dynamic call groups, logical groups, and run-time groups.

The dynamic call group contains exceptions badfunctioncallexception and Badmethodcallexception, Badmethodcallexception is a subclass of Badfunctioncallexception (a subclass of Logicexception), which means that these exceptions can be directly typed (the translator's note: The type of the exception itself, We all know that there are many kinds of anomalies, logicexception, or exception caught (the translator notes: Catch) When should you use these? Typically, you should be in a situation where an __call () method cannot be handled, or the callback cannot be a valid function (simply speaking, when something is not is_callable ()).

For example:

OO variantclass foo{Public Function __call ($method, $args) {  switch ($method) {case   ' Dobar ':/* ... */break;   Default:    throw new Badmethodcallexception (' Method '. $method. ' is not callable by this object ');  } }}//Procedural variantfunction foo ($bar, $baz) {$func = ' do ' $baz; if (!is_callable ($func)) {  throw new badfunct Ioncallexception (' Function '. $func. ' is not callable '); }}

A direct example of Call_user_func () at __call. This set of exceptions is useful when developing various API dynamic method calls and function calls, such as a request that can be sent and interpreted by the soap and XML-RPC client/server side.


The second group is the logical (logic) group. This group consists of domainexception, InvalidArgumentException, Lengthexception and Outofrangeexception. These exceptions are also subclasses of logicexception and, of course, subclasses of PHP's exception. Use these exceptions when there is a state variable, or an incorrect method/function parameter. To understand this better, let's take a look at the last set of exceptions

The last group is the run-time (runtime) group. It consists of outofboundsexception, OverflowException, Rangeexception, Underflowexception and Unexpectedvalueexceptio. These exceptions are also subclasses of RuntimeException and, of course, subclasses of PHP's exception. These exceptions (run-time groups) are called when the runtime function or method exception occurs.


How do logical groups and run-time groups work together? If you look at the anatomy of an object, it usually happens to be one of the two. First, the object will track and change state. This means that the object is usually not doing anything. It may pass the structure to it, it may set something through the setter and Getter (translator Note: For example $this->foo= ' foo '), or it may refer to other objects. Second, when the object does not track or change state, this means that it is working--doing what it should do. This is the runtime (runtime) of the object. For example, in an object's lifetime, it may be created, set something up, then it may be Setfoo ($foo), Setbar ($bar). At these times, any type of logicexception should be improved. In addition, when a method within an object is called with parameters, such as $object->dosomething ($someVariation), a logicexception may be thrown when the $somevariation variable is checked in the first few rows. After checking $somevariation, it continues to do the dosomething (), which is considered its "runtime", and in this code, the runtimeexcpetions exception may be thrown.


To understand better, let's look at the use of this concept in code:

Class foo{protected $number = 0; protected $bar = null;  Public function __construct ($options) {  /** This method throws a Logicexception exception **/} public   function Setnumber ($number) {  /** This method throws a Logicexception exception **/}   Public Function Setbar (Bar $bar) {  /** This method throws a Logicexception exception **/} public   function dosomething ($differentNumber {  if ($differentNumber! = $expectedCondition) {   /** here, throws Logicexception exception **/  }     /**   * here, This method throws a RuntimeException exception   */  }}

Now that this concept is understood, what does it do for the users of the code base? The user can determine the exception state of an object at any time, and they can catch (catch) exceptions with the specific type of the exception, such as InvalidArgumentException or lengthexception, or at least logicexception. With this level of precision adjustment, and the variety of types, they can use logicexception to capture the smallest exceptions, but can also get a better understanding of the actual exception types. The same concept applies to runtime exceptions, can throw more specific types of exceptions, and can be caught (catch), regardless of the specific or non-specific type of exception. It can provide users with more detailed information and accuracy.

Here is a table about SPL anomalies that you might be interested in

Best practices in class library code

PHP 5.3 brings new types of exceptions, as well as new best practices. In addition to standardizing some specific exceptions (such as: InvalidArgumentException, runtimeexception), it is also important to capture component-level exceptions. In this regard, ZF2 wiki and PEAR2 wiki are discussed in depth.

In short, in addition to the various best practices mentioned above, we should also use Marker Interface to create a component-level exception base class. By creating a component-level Marker Interface, exceptions that are used within a component can inherit both the exception type of SPL, and can be captured by various code at run time. Let's look at the following code:

Usage of bracket syntax for brevitynamespace mycompany\component {  interface Exception {}  class Unexpectedvalu Eexception   extends \unexpectedvalueexception   implements Exception {}  class Component {public  static function dosomething ()  {   if ($somethingExceptionalHappens) {    throw new unexpectedvalueexception (' Something bad happened ');   }  } } }

If you call mycompany\component\component in the code above::d the osomething () function, the exception thrown by dosomething () can be captured as the following exception type: PHP Exception, SPL Unexpectedvalueexception, the runtimeexception of the SPL, the mycompany\component\unexpectedvalueexception of the component, or the MyCompany\ of the component Component\exception. This provides great convenience for capturing exceptions in your class library components. In addition, by analyzing the type of the exception, we can also see the meaning of an exception.

Summary : The above is the entire content of this article, I hope to be able to help you learn.

Related recommendations:

Ways to parse HTML files using the Snoopy class

PHP Delete, convert, group, sort for arrays

PHP methods for file manipulation and string encryption

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.