Home > Article > Backend Development > Understanding and analyzing the exception mechanism in php_PHP tutorial
The exception mechanism in PHP can only be regarded as an imported product. PHP books rarely discuss the exception mechanism, and most of them only stay at the syntax stage. Some people praise PHP's exceptions as a good thing, while others think PHP's exceptions are ineffective. Some people are always confused whether exceptions should be used in PHP and how to use them?
The syntax of the exception itself is not worth discussing. The usage scenario of the exception is the main thing. Here I compare PHP and Java to see what the exceptions in PHP are and how they should be used.
I saw this discussion on the PPC forum and found it very valuable. I reorganized my views and made a summary.
First of all, what needs to be said is that the exception here refers to the exception of php. Because PHP's exceptions are very different from other languages.
Exceptions in php are situations that do not meet expectations during program operation, that is, a situation that is allowed to occur in the program execution process, but is different from the normal process. It is an abnormal situation, that is, errors that should not go wrong according to our normal logic, but still occur, are logical and business process errors, not grammatical errors.
An error in PHP is an illegal, grammatical or environmental problem that prevents the compiler from passing checks or even running.
What PHP's exception handling does is to handle certain situations that occur when your program is running. It is not an error. An exception is that the result obtained by the program is not what you want. For programs, exceptions are uncontrollable. We cannot control which links will go wrong during runtime, but we can roughly predict which links will go wrong and make targeted remedies.
The concepts and distinctions between exceptions and errors are different in various languages. In Java and PHP, the definitions of errors and exceptions are also different. In PHP, any error it encounters will trigger an error instead of throwing an exception (for some cases, both exceptions and errors will be thrown). Once PHP encounters abnormal code, it usually triggers an error instead of throwing an exception. In this sense, if you want to use exceptions to deal with unpredictable problems, you can't. For example, if you want to trigger an exception when the file does not exist and the database connection cannot be opened, it is not feasible. This is an error in PHP. PHP throws it as an error and cannot automatically catch it as an exception. Java is different. Java treats many behaviors as exceptions and can be caught.
Let’s take the most intuitive and simple example. Take the classic division by zero problem as an example:
The code is as follows | Copy code | ||||
//exception.php
|
Run result:
The following is the java code: ExceptionTry.java
代码如下 | 复制代码 |
//ExceptionTry.java public class ExcepetionTry { public static void tp() throws ArithmeticException{ int a; a=5/0; System.out.println("运算结果:"+a); } public static void main(String[] args) { int a; try { a=5/0; System.out.println("运算结果:"+a); } catch (ArithmeticException e) { e.printStackTrace(); }finally{ a = -1; System.out.println("运算结果:"+a); } try { ExcepetionTry.tp(); } catch (Exception e) { System.out.println("异常被捕获"); } } } |
Run result:
If we change the second statement in the tp method to the following:
a=5/1;
Then the result will be as follows:
It can be seen from the above running results that for "exceptional" codes such as division by 0, PHP considers this an error and will directly trigger the error (waring is also an error, but the error level is different), and will not automatically throw The exception causes the exception process to enter, so the final value of $a is not the expected -1, that is to say, the exception branch is not entered, and the exception is not handled. PHP can only catch exceptions after you actively throw them (this is generally the case, and there are some exceptions that PHP can automatically catch).
The exception handling mechanism will be used in the following three scenarios:
(1) Pessimistic prediction of the program
If a programmer is "pessimistic" about his code, it does not mean that the programmer's code is not of high quality. He believes that his code cannot handle various foreseeable and unforeseen situations one by one, so the programmer will perform exception handling. Assume a scenario where the programmer pessimistically believes that his code may cause a deadlock under high concurrency conditions. Then he will throw an exception pessimistically, and then catch the deadlock and handle the exception carefully.
(2) Program needs and business concerns
If programmers hope that the business code will not be filled with a lot of printing, debugging and other processing, they usually use the exception mechanism; or the business needs to define some of its own exceptions, at this time it is necessary to customize an exception to deal with the real world. Various businesses are supplemented. For example, if you are late for work, I consider this situation an anomaly. It should be collected and processed at the end of the month, and your salary will be deducted. If a programmer wants to predictably handle code that may affect normal business, then it needs to abnormal. Here, it is emphasized that exceptions are an essential part of business processing, and exceptions cannot be turned a blind eye. The exception mechanism believes that data consistency is very important. When data consistency may be destroyed, an exception mechanism is needed for pre-emptive remediation.
For example, if there is a business requirement to upload files, you need to save the uploaded files in a directory and insert the record of this file into the database. Then these two steps are an integrated business that are inseparable from each other. Not even one. Failure to save the file and successful insertion of the record will result in the failure to download the file; failure to write the file to the database will cause the file without records to become a dead file and never be downloaded.
Then we assume that there is no prompt after the file is successfully saved, but an exception is automatically thrown when the save fails. The same is true for accessing the database. There is no prompt when the insertion is successful, and an exception is automatically thrown when it fails. We can combine these two codes that may throw exceptions. The segment is wrapped in a try statement, and then the error is caught in the catch code segment. In the catch code segment, files that are not recorded in the database or records that do not have files are deleted to ensure the consistency of business data. Therefore, from a business perspective, exceptions focus on protecting the consistency of business data and emphasize the processing of abnormal business.
If our code only contains a symbolic try-catch, and finally prints an error, over. It is better not to use such anomalies, as they do not reflect the idea of anomalies. Therefore, the reasonable code should be as follows:
The code is as follows | Copy code |
代码如下 | 复制代码 |
try{ //可能出错的代码段 if(文件上传不成功) throw(上传异常); if(插入数据库不成功) throw(数据库操作异常);}catch(异常){ 必须的补救措施,如删除文件,删除数据库插入记录,这个处理很细致 } //.... ?> |
can also be as follows:
代码如下 | 复制代码 |
上传{ if(文件上传不成功) throw(上传异常); if(插入数据库不成功) throw(数据库操作异常); } //其他代码...try{ 上传; 其他; }catch(上传异常){ 必须的补救措施,如删除文件,删除数据库插入记录 }catch(其它异常){ 记录log } ?> |
The above two ways of catching exceptions, the former is to catch the exception immediately when it occurs; the latter is to scatter exceptions and catch them centrally. So which one should it be?
If our business is very important, then the sooner the exception is handled, the better, to ensure that the program can maintain consistency in business processing under unexpected circumstances. For example, if an operation has multiple prerequisite steps, and suddenly the last step is abnormal, then other prerequisite operations must be eliminated to ensure data consistency. And under this kind of core business, there is a lot of code to deal with the aftermath and perform data recovery. This is a relatively pessimistic anomaly.
If our exceptions are not that important, and in a single-entry, MVC-style application, in order to maintain the unity of the code process, the latter exception handling method is often used. This kind of exception handling puts more emphasis on the direction of the business process and is more important to the business process. The aftermath was not much of a concern. This is an optimistic anomaly.
(3) Language-level robustness requirements
At this point, php is missing. Take Java as an example. Java is a language oriented towards enterprise-level development and emphasizes robustness. Java supports multi-threading. Java believes that the interruption of multi-threads is completely unpredictable and avoidable. Therefore, Java stipulates that whenever multi-threading is used, this situation must be taken seriously. You either throw it and leave it alone, or you catch it and handle it. In short, you must face the InterruptedException exception and cannot avoid it. That is to say, important data services should be remedied after an exception occurs. Of course, you don't have to do it, but I will tell you that this is what you should do. This type of exception is mandatory. Additional exceptions are optional and are left to the programmer's discretion. This classification and restriction of exceptions by Java ensures the robustness and reliability of Java programs.
So what’s the point of exception?
An exception is an uncontrollable runtime error, which will interrupt the normal logic operation when an error occurs. The logic behind the exception code cannot continue to run. Then the advantage of try/catch is that it can reduce the logical interruption and damage caused by exceptions to the minimum range, and the integrity of the business logic will not be affected after remedial measures. Throwing exceptions and just throwing without catching, or catching without remediation, This will lead to data confusion. This is an important role of exception handling. When we accurately control the runtime process, when the program is interrupted, we can predictably use try to reduce the scope of possible errors, and then promptly capture the occurrence of exceptions and make corresponding remedies. So that the logical flow can still get back on track.
How to check php exceptions?
We have seen that the exception mechanism in PHP is very useless. In most cases, exceptions cannot be thrown automatically. If-else must be used to judge first and then throw exceptions manually. This approach seems to be unnecessary. The significance of manually throwing exceptions is not very big, because if you throw exceptions manually, it means that you have fully anticipated the occurrence of errors in the code, and it is not considered a real "exception", but is expected. . Still stuck in complicated business logic judgment and processing. What Java and C++ languages do best is that they define a bunch of built-in common exceptions. They don't require programmers to judge various exceptions and throw them manually. The compiler will judge on our behalf whether an error has occurred in the business and automatically throw exceptions. . As a programmer, you only need to care about the capture and subsequent remediation of exceptions, instead of focusing on which exceptions will occur like in PHP. You use if-else to judge one by one and throw exceptions one by one.
The exception mechanism of PHP is not perfect. In many cases, it has no obvious advantages compared with if-else. This is also the reason why PHP exceptions are not popular. Of course, using exceptions can also reduce coupling to a certain extent.
So how to improve PHP’s original exception handling mechanism? At this time, it is necessary to use PHP's error handling. PHP provides a set_error_handler function, which allows you to customize error handling functions and transfer non-fatal error handling to your own defined functions for analysis and processing. But because there may be many things that go wrong and the situations that need to be distinguished are very complicated if processed centrally, we only use this feature as a springboard. In the custom function, we manually throw an exception to get back to work, so that try/catch can capture and handle the interruption caused by this runtime error, thus achieving the purpose of expanding the scope of influence of try/catch.