Best practices for exceptions in PHP5.3. Exception in PHP5.3 best practices each new feature will create an exponential random number when added to the PHP runtime, in this way, developers can use and even abuse the best practices of this new feature exception in PHP 5.3.
Every new function is added to the PHP runtime to create an exponential random number. in this way, developers can use and even abuse this new feature. However, developers did not reach a consensus until there were some good and bad use cases. As these new cases emerge, we can finally identify what is the best or the worst.
Exception handling is indeed not a new feature in PHP anyway. However, in this article, we will discuss two new features of exception handling in PHP 5.3. The first is Nested exceptions. The second is a core extension of SPL's current PHP operating mechanism. These two new features can be found in this book best practices worthy of further research.
Note: Some of these features already exist in PHP versions earlier than 5.3, or at least can be implemented in PHP versions earlier than 5.3. when PHP 5.3 is mentioned in this article, it is not the PHP runtime version that is strictly responsible. on the contrary, it means that the code library and project adopt PHP 5.3 as the lowest version, but it also shows all the best practices in the new development phase. this development phase highlights the "2.0" attempts made by specific projects such as Zend Framework, Symfony, Doctrine, and PEAR.
Background
PHP 5.2 has only one Exception class Exception. According to the Zend Framework/PEAR development standard, this class is the base class of all exception classes in your library. If you create a library named MyCompany, all the code files in the library will start with MyCompany _ according to the Zend Framework/PEAR standard. If you want to create your own Exception base class: MyCompany_Exception for the database, use this class to inherit the Exception, and then inherit and throw the Exception class from the component. For example, if you have a component MyCompany_Foo, you can create an exception base class MyCompany_Foo_Exception for the component. These exceptions can be caught by codes that capture MyCompany_Foo_Exception, MyCompany_Exception, or Exception. For other code in the library that uses this component, this is a layer-3 exception (or more, depending on the number of child classes of MyCompany_Foo_Exception). they can handle these exceptions as needed.
In php5, basic exception classes support nested features. What is nesting? Nesting is a capability that can capture special exceptions or catch a new exception object created with reference to the original exceptions. This will allow the caller attribute to be reflected in the two exception classes in the more open overhead library, and of course it will also be reflected in the exception classes with the original exception behavior.
Why are these features very useful? Generally, it is the most effective code to throw exceptions of its own type by using other code. The code may be code of a third-party code library that encapsulates some adaptive functions using the adapter mode, or a simple code that throws exceptions using some PHP extensions.
For example, in component Zend_Db, it uses the Adapter mode to encapsulate specific PHP extensions to create a database abstraction layer. in an adapter, Zend_Db encapsulates PDO, and PDO throws its own exception PDOException. Zend_Db needs to capture these PDO-specific exceptions, and let them be thrown again with the expected and known type Zend_Db_Exception. this ensures that Zend_Db will always throw exceptions of the Zend_Db_Exception type (so they can be captured), and they can also access the PDOException thrown at the very beginning as needed.
The following example shows how a fictitious database adapter can implement embedded exceptions:
- 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 must call 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 rather than terminating errors. Extensions that can throw exceptions in PHP include PDO, DOM, Mysqli, Phar, Soap, and SQLite.
New feature: new core exception type
In PHP 5.3 development, we showed some interesting new exception types. These exceptions already exist in PHP 5.2.x, but they have not recently come to the "reevaluate" best practices, and now they are even more eye-catching. They have been applied in SPL extensions and listed here in the manual) because these new exception types are part of the core of PHP and part of SPL, they can be used by anyone who uses PHP 5.3 or above) to run code. Although it does not seem so important when writing code at the application layer, it is even more important to use these new exception types when we write or use code libraries.
So why is the new exception of the normal type? In the past, developers tried to add more content to the exception message to give the exception more meaning. Although this is feasible, it has several disadvantages. First, you cannot capture message-based exceptions. This is a problem. if you know that a group of codes are of the same exception type and different prompt messages correspond to different exceptions, the processing will be quite difficult. For example, for an authentication class, in the $ auth-> authenticate (); it throws exceptions for the same type of assumptions), but different messages correspond to two specific faults: the cause of the failure is that the authentication server cannot reach the same exception type, but the verification message indicating the failure is different. In this case, note that using exceptions may not be the best way to handle authentication responses). This will require the use of strings to parse messages to process these two different situations.
The solution to this problem is obviously to encode the exception in some way, so that it is easier to query when you need to identify how to respond to this abnormal environment. The first response library uses the $ code attribute of the exception base class. The other is to create a subclass or a new exception class that can be thrown and can describe its own behavior. These two methods have the same obvious disadvantages. Neither of them presents the best example. Neither of them is considered a standard, so every project that tries to replicate the two solutions will have minor changes, this forces the use to go back to the document to understand the specific solutions already in the created Library. Now, by using the new SPL type method, also known as the php Standard Library, developers can use the same method in their projects, and new best methods for reusing these projects have emerged.
The second disadvantage is that the use of detailed information makes it very difficult for non-English or English-speaking developers to understand such exceptions. This may make the developer very slow in trying to understand the meaning of the exception information. Many developers will also write articles about exceptions, because there is not yet a unified integrated standard which should have different versions with the same number of developers to describe the situation described by the exception message.
So how can I use them to describe the details that make people speechless?
Currently, there are 13 new exception types in SPL. Two of them can be considered as the base class: logical exception and runtime exception; both inherit the php exception class. Other methods can be logically divided into three groups: Dynamic Call group, logical group, and runtime group.
A Dynamic Call group contains abnormal BadFunctionCallException and BadMethodCallException, and BadMethodCallException is a subclass of BadFunctionCallExceptionLogicException. This means that these exceptions can be directly typed by their translators. note: they are the types of exceptions, we all know that there are many exceptions), LogicException, or Exception catch translator note: catch) when should you use these? Generally, you should generate a _ call () method that cannot be processed, or callback cannot be a valid function. Simply put, 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');
- }
- }
In a direct example, call_user_func () is used in _ call (). This group of exceptions is useful when developing call and function calls for various API dynamic methods, such as a request that can be sent and interpreted by the SOAP and XML-RPC clients/servers.
The second group is logic.Logic. This group consists of DomainException, InvalidArgumentException, LengthException, and OutOfRangeException. These exceptions are also subclasses of LogicException and, of course, exceptions of PHP. These exceptions are used when there is an indefinite status or an incorrect method/function parameter. To better understand this, let's first look at the last group of exceptions.
The last group is runtime.Runtime. It consists of OutOfBoundsException, OverflowException, RangeException, UnderflowException, and unexpectedvalue1_tio. These exceptions are also subclasses of RuntimeException, and are also subclasses of PHP Exception. During "running"Runtime).
How do logical groups and runtime groups work together? If you look at the analysis of objects, it is usually one of the two. First, the object will be tracked and changed. This means that the object usually does not do anything. It may pass the structure to it, and it may set something through setter and getter. note: for example, $ this-> foo = 'Foo'), or, it may reference other objects. Second, when the object does not track or change the state, this means it is performing an operation-doing what it should do. This is the runtime of the object ). For example, in the lifetime of an object, it may be created and set something, so it may be setFoo ($ foo), setBar ($ bar ). In these cases, LogicException of any type should be raised. In addition, a LogicException may be thrown when the methods in the object are called with parameters, such as $ object-> doSomething ($ someVariation. After checking $ someVariation, it continues to do the doSomething () it is considered as its "runtime" runtime). in this code, it may throw a RuntimeExcpetions exception.
For better understanding, let's take a look at the application of this concept in code:
- Class Foo
- {
- Protected $ number = 0;
- Protected $ bar = null;
-
- Public function _ construct ($ options)
- {
- /** This method throws a LogicException **/
- }
-
- Public function setNumber ($ number)
- {
- /** This method throws a LogicException **/
- }
-
- Public function setBar (Bar $ bar)
- {
- /** This method throws a LogicException **/
- }
-
- Public function doSomething ($ differentNumber)
- {
- If ($ differentNumber! = $ ExpectedCondition ){
- /** Here, a LogicException exception is thrown **/
- }
-
- /**
- * Here, this method throws a RuntimeException.
- */
- }
-
- }
Now that we understand this concept, what does it do for users of the code library? Users can determine the exception status of objects at any time. They can catch exceptions with specific types of exceptions, such as InvalidArgumentException or LengthException, which is at least LogicException. With this level of precision adjustment and diversity of types, they can catch the smallest exception with LogicException, but they can also get a better understanding through the actual exception types. The same concept applies to runtime exceptions. more specific types of exceptions can be thrown, and catch can be caught, whether it is a specific or non-specific type exception ). It provides users with more detailed information and accuracy.
The following is a table about SPL exceptions. you may be interested in
Best Practices in class library code
PHP 5.3 brings new exception types and new best practices. in addition to standardizing certain exceptions (such as InvalidArgumentException and RuntimeException), it is also important to capture component-level exceptions. in this regard, ZF2 wiki and PEAR2 wiki have in-depth discussions.
In short, apart from the best practices mentioned above, we should also use the Marker Interface to create a component-level exception base class. by creating a component-level Marker Interface, exceptions used in the component can inherit the SPL exception type and be captured by various code at runtime. 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 the MyCompany \ Component: doSomething () function in the above code, the exceptions thrown by doSomething () can be caught as the following Exception types: PHP Exception, SPL UnexpectedValueException, runtimeException of SPL, MyCompany \ Component \ UnexpectedValueException of the Component, or MyCompany \ Component \ Exception of the Component. this provides great convenience for capturing exceptions in your class library components. in addition, by analyzing the types of exceptions, we can also see the meaning of an exception.
Summary
All in all, this article aims to teach you the best standard practice of creating and throwing exceptions, that is, you should pay more attention to the types of exceptions and less tangle error messages of exceptions. If you have any comments, please leave a message here, on the PHP document webpage, or on the ZF2 wiki link provided above.
PHP 5.3 best practices each new feature will create an exponential random number when added to the PHP runtime. in this way, developers can use and even abuse this new feature...