Best practices for exceptions in PHP 5.3
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) of 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 {
- $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 assumed
- try {
- $db = New mycompany_database (' PDO ', $connectionParams);
- $db ->executequery ($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 here in the manual) 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 with 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 $auth->authenticate (); It throws an exception for the same type of assumption is 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 fails to prompt the validation message differently. In this case, note that using an exception might not be the best way to handle the authentication response, which would 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 badfunctioncallexceptionlogicexception, which means that these exceptions can be referred to by their direct type translator: The type of the exception itself, We all know that there are many kinds of anomalies, logicexception, or exception caught the translator note: is catch) when should you use these? Typically, you should be in a situation where a __call () method cannot be handled, or a callback cannot be used without a valid function simply said when something is not is_callable ()).
For example:
- //OO variant
- class Foo
- {
- Public function __call ($method, $args)
- {
- Switch ($method) {
- Case ' Dobar ':/ * ... * /break;
- default :
- Throw New badmethodcallexception (' Method ' ) . $method . ' is not callable by this object ' );
- }
- }
-
- }
-
- //Procedural variant
- function foo ($bar, $baz) {
- $func = ' Do ' . $baz ;
- if (! is_callable ($func)) {
- Throw New badfunctioncallexception (' 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 runtime 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 exception run-timegroups are called when a function or method exception occurs at runtime Runtime)
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 by 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 its dosomething (), which is considered its "runtime" runtime, and in this code, it is possible to throw a runtimeexcpetions exception.
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, throw 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, which can throw more specific types of exceptions, and catches can be caught 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 brevity
- Namespace Mycompany\component {
-
- Interface Exception
- {}
-
- class unexpectedvalueexception
- 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.
Summarize
All in all, this article is intended to teach you the best standard practice of creating and throwing exceptions, that is, you should pay more attention to the type of exception and less tangle with abnormal error messages. If you have any comments, please feel free to leave a message here, or on the PHP documentation page or on the link ZF2 wiki.
http://www.bkjia.com/PHPjc/946150.html www.bkjia.com true http://www.bkjia.com/PHPjc/946150.html techarticle Exceptions in PHP 5.3 Best practices each new feature added to PHP runtime creates an exponential random number, in such a way that developers can use and even abuse this new feature ...