浅谈PHP异常处理

一、PHP中异常的独特性

  PHP中的异常的独特性,即PHP中的异常不一样于主流语言C++、java中的异常。在Java中,异常是惟一的错误报告方式,而在PHP中却不是这样,而是把全部不正常的状况都视做了错误进行处理。这两种语言对异常和错误的界定存在分歧。什么是异常什么是错误,两种语言的设计者存在不一样的观点。php

  PHP中的异常:html

  是程序在运行中出现不符合预期的状况及与正常流程不一样的情况。一种不正常的状况,按照正常逻辑本不应出的错误,但仍然会出现的错误,这是属于逻辑和业务流程的错误,而不是编译或者语法上的错误。java

  PHP中的错误:程序员

  是属于php脚本自身的问题,大部分状况是由错误的语法,服务器环境致使,使得编译器没法经过检查,甚至没法运行的状况。warning、notice都是错误,只是他们的级别不一样而已,而且错误是不能被try-catch捕获的。服务器

   在PHP中遇到任何自身错误都会触发一个错误,而不是抛出异常。PHP一旦遇到非正常代码,一般都会触发错误,而不是抛出异常。所以,若是想要使用异常处理不可预料的问题,是办不到的。函数

典型例子:学习

1 <?php
2 
3 try {
4     echo 1/0;
5 } catch (Exception $e){
6     echo $e->getMessage();
7 }

结果:测试

结果显示:编码

  此时出现了一个警告级别的错误,程序终止。spa

结论:
  PHP一般是没法自动捕获有意义的异常,它把全部不正常的状况都视做了错误,你要想捕获异常就得使用if....else结构,保证代码是正常的,而后判断进行手动抛出异常。

二、PHP中的错误级别

   PHP中的异常机制是不足的,绝大多数状况下没法自动抛出异常,必须使用if....else语句先进行判断,在进行手动抛出异常。

  手动抛出异常的意义不大,是已经预料到的错误,这种方式将会使你陷入纷繁复杂的业务逻辑判断和处理中。

  所以咱们能够经过一些特殊的函数来自定义错误处理函数,来接管PHP原生的错误处理函数,而后再进行抛出异常。

  接下来咱们须要了解PHP中的一些错误。

错误显示控制:

  【ALL设置】

  全局:php.ini中设置display_error = on/off;

  局部:ini_set("display_error", true/false);

PHP.ini中display_errors = Off失效的解决 
  问题: PHP设置文件php.ini中明明已经设置display_errors = Off,可是在运行过程当中,网页上仍是会出现错误信息。 
  解决: 经 查log_errors= On,据官方的说法,当这个log_errors设置为On,那么必须指定error_log文件,若是没指定或者指定的文件没有权限写入,那么照样会输 出到正常的输出渠道,那么也就使得display_errors 这个指定的Off失效,错误信息仍是打印了出来。因而将log_errors = Off,问题就解决了。

  【选择性设置显示错误】

  全局:error_reporting = E_ALL | E_STRICT....

  局部:error_reporting(E_ERROR | E_WARNING | E_PARSE)

1     E_ERROR           致命的运行错误。错误没法恢复,暂停执行脚本。
2     E_WARNING         运行时警告(非致命性错误)。非致命的运行错误,脚本执行不会中止。
4     E_PARSE           编译时解析错误。解析错误只由分析器产生。
8     E_NOTICE          运行时提醒(这些常常是你代码中的bug引发的,也多是有意的行为形成的。)
16    E_CORE_ERROR PHP  启动时初始化过程当中的致命错误。
32    E_CORE_WARNING    PHP启动时初始化过程当中的警告(非致命性错)。
64    E_COMPILE_ERROR   编译时致命性错。这就像由Zend脚本引擎生成了一个E_ERROR。
128   E_COMPILE_WARNING 编译时警告(非致性错)。这就像由Zend脚本引擎生成了E_WARNING警告。
256   E_USER_ERROR      自定义错误消息。像用PHP函数trigger_error(程序员设置E_ERROR)
512   E_USER_WARNING    自定义警告消息。像用PHP函数trigger_error(程序员设的E_WARNING警告) 
1024  E_USER_NOTICE     自定义的提醒消息。像由使用PHP函数trigger_error(程序员E_NOTICE集)
2048  E_STRICT          编码标准化警告。容许PHP建议修改代码以确保最佳的互操做性向前兼容性。 
4096  E_RECOVERABLE_ERROR   开捕致命错误。像E_ERROR,但能够经过用户定义的处理捕获(又见set_error_handler())
8191  E_ALL             全部的错误和警告(不包括 E_STRICT) (E_STRICT will be part of E_ALL as of PHP 6.0)14 16384 E_USER_DEPRECATED 15 30719 E_ALL

   一共有十五种,使用二进制代替,0000 0000 0000 0011 表示 E_ERROR和E_WARNING

  例如:

  error_reporting(3);  //只显示E_ERROR和E_WARNING错误

  error_reporting(-1);  //只显示全部错误误

 注意:

  在开发阶段一般是显示全部错误,方便解决问题;

  在生产阶段一般是隐藏错误,并将需错误记录到文件中(错误日志);

  php.ini中设置:log_error = on/off;  //记录、不记录

         error_log = php_errors.log  //设定错误日志文件(此时没有给定路径则在当前位置生成)

  还能够经过ini_set()进行设置。

 

三、PHP中的异常处理

  3.一、set_error_handler(error_function, error_type)

  使用set_error_handler(error_function, error_type)函数设置自定义错误处理函数,接管原错误处理函数。

eg.

 1 <?php
 2 
 3 // 方式一
 4 // set_error_handler('myError');
 5 // function myError($errorNum, $errorMs, $errorFile, $errorLine){
 6 //     echo('set_error_handler: ' . $errorNum . ':' . $errorMs . ' in ' . $errorFile . ' on ' . $errorLine . ' line ');
 7 // }
 8 
 9 // 方式二
10 class ErrorClass{
11     // 必须静态public方法
12     public static function myError($errorNum, $errorMs, $errorFile, $errorLine){
13     echo('set_error_handler: ' . $errorNum . ':' . $errorMs . ' in ' . $errorFile . ' on ' . $errorLine . ' line ');
14     }
15 }
16 
17 set_error_handler(['ErrorClass', 'myError']);
18 
19 
20 try {
21     $a = 5/0;
22 } catch (Exception $e) {
23     echo "666666";
24 }

访问结果:

  由结果可知:咱们自定义的myError方法截取了错误,此时咱们能够主动的处理这些错误,抛出相应的异常。

  可是咱们须要注意如下两点:

  第一,若是存在该方法,相应的error_reporting()就不能在使用了。它将接管PHP原生错误处理函数,即全部的错误都会交给自定义的函数处理。
  第二,此方法不能处理如下级别的错误:E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,set_error_handler() 函数所在文件中产生的E_STRICT,该函数只能捕获系统产生的一些Warning、Notice级别的错误。
注意:
  若是在脚本执行前发生错误,因为此时自定义的错误处理函数尚未注册,所以就用不到这个自定义错误处理程序。

  3.二、register_shutdown_function(exception_function) 

  捕获PHP的错误:Fatal Error、Parse Error等, 这个方法是PHP脚本执行结束前最后一个调用的函数,好比脚本错误、die()、exit、异常、正常结束都会调用。
  经过这个函数就能够在脚本结束前判断此次执行是否有错误产生,这时就要借助于一个函数:error_get_last();这个函数能够拿到本次执行产生的全部错误。error_get_last();返回的信息:
  [type]            - 错误类型
  [message]    - 错误消息
  [file]              - 发生错误所在的文件
  [line]             - 发生错误所在的行
注意:当parse-time出错时是不会调用本函数的。只有在run-time出错的时候,才会调用本函数。即须要成功注册此函数才能使用。【测试3和测试4对比】

 eg.

 1 <?php
 2                 
 3 try {
 4     $a = 5/0;
 5 } catch (Exception $e) {
 6     echo "666666";
 7 }
 8     
 9 register_shutdown_function('myshutdownfunc');
10 function myshutdownfunc()
11 {
12     if ($error = error_get_last()) {
13         echo "<pre>";
14         print_r($error);
15         echo "</pre>";die;
16     }
17 }

 

测试1:

测试2:(使用echo "string";替换try....catch)

测试3:(使用echo "string"替换try...catch)

此时语法错误,register_shutdown_function函数未执行

 

测试4:

新建一个文件,具备语法错误的php代码,并将其引入执行文件中,例如

 1 ceshi2.class.php文件
 2 <?php
 3 echo "string"
 4 
 5 ?>
 6 
 7 ceshi.class.php文件
 8 <?php
 9 
10 register_shutdown_function('myshutdownfunc');
11 function myshutdownfunc()
12 {
13     if ($error = error_get_last()) {
14         echo "<pre>";
15         print_r($error);
16         echo "</pre>";die;
17     }
18 }
19 
20 include "ceshi2.class.php";
21 ?>

 结果:

  3.三、set_exception_handler(exception_function)

 

参数 描述
error_function 必需。规定未捕获的异常发生时调用的函数。
该函数必须在调用 set_exception_handler() 函数以前定义。
这个异常处理函数须要须要一个参数,即抛出的 exception 对象。

做用:

  set_exception_handler() 函数设置用户自定义的异常处理函数。

  该函数用于建立运行时期间的用户本身的异常处理方法。

  该函数会返回旧的异常处理程序,若失败,则返回 null。

提示:在这个异常处理程序被调用后,脚本会中止执行。 

 eg.

 1 <?php
 2 // 第一种放方法
 3 // function myException($exception) {
 4 //     echo "<b>Exception:</b> " , $exception->getMessage();
 5 // }
 6 // set_exception_handler('myException');
 7  
 8 // 第二种方法
 9 class MyError{
10     //必须是静态public方法
11     public static function myException($exception) {
12         echo "<b>Exception:</b> " , $exception->getMessage();
13     }
14 }
15 set_exception_handler(['MyError', 'myException']);
16 throw new Exception('Uncaught Exception occurred---没有人处理的异常');

运行结果:

 

 做者:那一叶随风

 原文地址:http://www.cnblogs.com/phpstudy2015-6/p/8433541.html

 声明:本博客文章为原创,只表明本人在工做学习中某一时间内总结的观点或结论。转载时请在文章页面明显位置给出原文连接

相关文章
相关标签/搜索