PHP自学之路----错误及异常处理机制、错误日志

PHP错误机制

 

在 PHP 中,默认的错误处理很简单。一条消息会被发送到浏览器,这条消息带有文件名、行号以及一条描述错误的消息。在创建脚本和 web 应用程序时,错误处理是一个重要的部分。如果您的代码缺少错误检测编码,那么程序看上去很不专业,也为安全风险敞开了大门。

 PHP 中一些最为重要的错误检测方法。

  • 简单的 "die()" 语句

      

[html] view plain copy
 
 print?
  1. if(!file_exists("../func.php")){  
  2.         die("文件不存在<br/>");  
  3.     } else {  
  4.         $fp=fopen("../func.php","r");  
  5.         echo "文件打开成功<br/>";  
  6.         //..关闭  
  7.         fclose($fp);  
  8.     }      
  • 更简洁的方式

[html] view plain copy
 
 print?
  1. file_exists("func.php") or die("文件不存在<br/>");  

  这句相当于把上面的if...else合并到一起了!

  • 创建自定义错误检测机制

     看下面的代码,假设文件是不存的运行的时候会报错如下:

[html] view plain copy
 
 print?
  1. <?php  
  2. $file=fopen("welcome.txt","r");  
  3. ?>  

错误信息如下(PHP默认的错误处理机制):

[html] view plain copy
 
 print?
  1. Warning: fopen(welcome.txt) [function.fopen]: failed to open stream:   
  2. No such file or directory in C:\webfolder\test.php on line 2  


 

创建一个自定义的错误处理器非常简单。我们很简单地创建了一个专用函数,可以在 PHP 中发生错误时调用该函数。该函数必须有能力处理至少两个参数 (error level 和 error message),但是可以接受最多五个参数(可选的:file, line-number 以及 error context):

    系统自带的错误函数:

[html] view plain copy
 
 print?
  1. error_function(error_level,error_message,error_file,error_line,error_context)  


参数分析:

 

参数描述
error_level

必需。为用户定义的错误规定错误报告级别。必须是一个值数。

参见下面的表格:错误报告级别。

error_message 必需。为用户定义的错误规定错误消息。
error_file 可选。规定错误在其中发生的文件名。
error_line 可选。规定错误发生的行号。
error_context 可选。规定一个数组,包含了当错误发生时在用的每个变量以及它们的值。

 

错误报告级别

这些错误报告级别是错误处理程序旨在处理的错误的不同的类型:

常量描述
2 E_WARNING 非致命的 run-time 错误。不暂停脚本执行。
8 E_NOTICE

Run-time 通知。

脚本发现可能有错误发生,但也可能在脚本正常运行时发生。

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。
4096 E_RECOVERABLE_ERROR 可捕获的致命错误。类似 E_ERROR,但可被用户定义的处理程序捕获。(参见 set_error_handler())
8191 E_ALL

所有错误和警告,除级别 E_STRICT 以外。

(在 PHP 6.0,E_STRICT 是 E_ALL 的一部分)

 

错误报告级别

 

这些错误报告级别是错误处理程序旨在处理的错误的不同的类型:

 

常量描述
2 E_WARNING 非致命的 run-time 错误。不暂停脚本执行。
8 E_NOTICE

Run-time 通知。

脚本发现可能有错误发生,但也可能在脚本正常运行时发生。

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。
4096 E_RECOVERABLE_ERROR 可捕获的致命错误。类似 E_ERROR,但可被用户定义的处理程序捕获。(参见 set_error_handler())
8191 E_ALL

所有错误和警告,除级别 E_STRICT 以外。

(在 PHP 6.0,E_STRICT 是 E_ALL 的一部分)

 

下面是我们自己实现的错误处理函数:

[html] view plain copy
 
 print?
  1. <?php  
  2. //自定义自己的错误处理函数  
  3.     function myerror($errno,$errstr){  
  4.         echo "<font size='5' color='red'>$errno</font><br/>";  
  5.         echo "错误信息:".$errstr;  
  6.     }  
  7.     //这里我们还需要改写set_error_handler  
  8.     /*PHP 的默认错误处理程序是内建的错误处理程序。我们打算把上面的函数改造为脚本运行期间的默认错误处理程序。set_error_handler() 仅需要一个参数,可以添加第二个参数来规定错误级别。  
  9.      */  
  10.   
  11.     set_error_handler("myerror",);  
  12.   
  13.     echo($test);  
  14.     /*输出下面的内容:  
  15.      8  
  16.      错误信息:Undefined variable: test  
  17.      */  
  18. ?>  


错误触发器:

   错误触发器和错误处理器区别:触发器往往处理逻辑上的错误,处理器处理系统上的错误:

 看下面的需求:当输入年龄大于120时,会触发错误!

[html] view plain copy
 
 print?
  1. $age = 200;  
  2.  if($age>120){  
  3.       trigger_error("the age is logger!",E_USER_WARNING);  
  4.       exit();  
  5.  }  

运行上面的代码会出现下面的错误:

Warning: the age is logger! in /var/myphp/exec/File.php on line 3

看处理器一样,上面的警告信息是系统打印出来的。那么我们将处理器和错误触发器共同使用,看下面的代码:

[html] view plain copy
 
 print?
  1.     <?php //自定义自己的错误处理函数  
  2.     function myerror($errno,$errstr){  
  3.         echo "<font size='5' color='red'>$errno</font><br/>";  
  4.         echo "错误信息:".$errstr;  
  5.     }  
  6.     //指定错误的处理函数,  
  7.      set_error_handler("myerror",E_USER_WARNING);  
  8.      $age = 200;  
  9.      if($age>120){  
  10.          //E_USER_WARNING 这里必须和制定错误处理函数对应,否则还是会调用系统错误处理函数  
  11.           trigger_error("the age is logger!",E_USER_WARNING);  
  12.           exit();  
  13.      }  
  14.      /*512  
  15.      错误信息:the age is logger!  
  16.      */  
  17. ?>  

可能的错误类型:

  • E_USER_ERROR - 致命的用户生成的 run-time 错误。错误无法恢复。脚本执行被中断。
  • E_USER_WARNING - 非致命的用户生成的 run-time 警告。脚本执行不被中断。
  • E_USER_NOTICE - 默认。用户生成的 run-time 通知。脚本发现了可能的错误,也有可能在脚本运行正常时发生。

 错误日志:

http://blog.csdn.net/heiyeshuwu/article/details/577838 这个博客有介绍,可以看看!

 默认地,根据在PHP.ini中的error_log配置,PHP想服务器的错误记录系统或者文件发送错误日志,通过使用error_log()函数,您可以向指定的文件或远程目的地发送错误记录

 bool error_log ( string message [, int message_type [, string destination [, string extra_headers]]] )

 
[php] view plain copy
 
 print?
  1. <?php  
  2.   
  3.   
  4.      //设置时区  
  5.      date_default_timezone_set("Asia/Chongqing");  
  6.     //自定义自己的错误处理函数  
  7.     function myerror($errno,$errstr){  
  8.         $error_info="错误信息:".$errno.$errstr;  
  9.         error_log(date("Y-m-d G-i-s").$error_ingo."\r\n",3,"1.txt");  
  10.     }  
  11.      set_error_handler("myerror",E_USER_WARNING);  
  12.      $age = 200;  
  13.      if($age>120){  
  14.           trigger_error("the age is logger!",E_USER_WARNING);  
  15.           exit();  
  16.      }  
  17.   
  18. ?>  

二、PHP异常处理【重点】
 

基本语法:

try{
            //可能出现错误或异常的代码
            //catch 捕获  Exception是php已定义好的异常类
        } catch(Exception $e){
            //对异常处理,方法:
                //1、自己处理
                //2、不处理,将其再次抛出
        }

 

处理处理程序应当包括:
  1. Try - 使用异常的函数应该位于 "try"  代码块内。如果没有触发异常,则代码将照常继续执行。但是如果异常被触发,会抛出一个异常。
  2. Throw - 这里规定如何触发异常。每一个 "throw" 必须对应至少一个 "catch"
  3. Catch - "catch" 代码块会捕获异常,并创建一个包含异常信息的对象   
看下面的例子:
[php] view plain copy
 
 print?
  1. <?php  
  2.     //创建一个抛出异常的函数  
  3.     function checkNum($number){  
  4.         if($number >1){  
  5.             throw new Exception("Value must be 1 or little!<br/>");  
  6.         }  
  7.         return true;  
  8.     }  
  9.     //在 try 代码块中触发异常  
  10.     try{  
  11.         $num = 2;  
  12.         checkNum($num);//AAAA  
  13.         echo "如何抛出异常,这个将不会被执行!<br/>";  
  14.     }catch(Exception $e){  
  15.         //捕获异常  
  16.         echo 'Message:'.$e->getMessage();  
  17.     }  
  18.     echo "继续执行<br/>";  
  19. ?>  

当$num=2;将会抛开异常,打印下面的语句:
Message:Value must be 1 or little!
继续执行
当$num=0;将会抛开异常,打印下面的语句:
如何抛出异常,这个将不会被执行!
继续执行
从上面可以得出下面的结论:
 1、出捕获异常并不会干扰下面代码的执行!
 2、如果异常抛出,其后面的语句将不会被执行;
 
看下面的代码我们自己设置定义异常处理函数:
[php] view plain copy
 
 print?
  1. <?php  
  2.   
  3.     function my_exception($e){  
  4.         echo "我是顶级处理器:".$e->getMessage.$e->getline;  
  5.     }  
  6.     //修改默认的顶级异常处理函数  
  7.     set_exception_handler("my_exception");  
  8.     function a1($val){  
  9.         if($val>100){  
  10.             //抛出异常  
  11.             throw new Exception("val > 100!<br/>");  
  12.         }  
  13.     }  
  14.     function a2($val){  
  15.         if($val=="jsh"){  
  16.             //抛出异常  
  17.             throw new Exception("val  jsh!<br/>");  
  18.         }  
  19.     }  
  20.   
  21.     try{  
  22.         a2("jsh");//这是会抛出异常  
  23.     }catch(Exception $e){  
  24.         //获取异常  
  25.         echo $e->getMessage();  
  26.         //可以继续抛出,这是会启动PHP默认的异常处理机制  
  27.         //我们可以自己定义一个顶级异常处理函数  
  28.         throw $e;  
  29.     }  
  30. ?>  
 

异常的规则:

1、需要进行异常处理的代码放入try代码块内,以便捕获潜在的异常。
2、每个try或者,throw代码块至少拥有一个catch代码。
3、使用多个catch代码块可以捕获不同种类的异常。
   try{
        XXXXXX;
   }catch(my_exception $e){//自己定义的异常处理函数
        XXXXXX;
   }catch(Exception $3){//系统自带的异常处理函数
        XXXXX;
    } 
4、可以在try代码块中再次抛出异常
5,如果抛出了异常,就必须捕获他,获知使用顶级异常处理机制。

看下面的代码示例,是在PHP手册中的,仔细获得下吧

[php] view plain copy
 
 print?
  1. <?php  
  2. /** 
  3. * 自定义一个异常处理类 
  4. */  
  5. class MyException extends Exception  
  6. {  
  7.     // 重定义构造器使 message 变为必须被指定的属性  
  8.     public function __construct($message, $code = 0) {  
  9.         // 自定义的代码  
  10.   
  11.         // 确保所有变量都被正确赋值  
  12.         parent::__construct($message, $code);  
  13.     }  
  14.   
  15.     // 自定义字符串输出的样式 */  
  16.     public function __toString() {  
  17.         return __CLASS__ . ": [{$this->code}]: {$this->message}\n";  
  18.     }  
  19.   
  20.     public function customFunction() {  
  21.         echo "A Custom function for this type of exception\n";  
  22.     }  
  23. }  
  24.   
  25.   
  26. /** 
  27. * 创建一个用于测试异常处理机制的类 
  28. */  
  29. class TestException  
  30. {  
  31.     public $var;  
  32.   
  33.     const THROW_NONE    = 0;  
  34.     const THROW_CUSTOM  = 1;  
  35.     const THROW_DEFAULT = 2;  
  36.   
  37.     function __construct($avalue = self::THROW_NONE) {  
  38.   
  39.         switch ($avalue) {  
  40.             case self::THROW_CUSTOM:  
  41.                 // 抛出自定义异常  
  42.                 throw new MyException('1 is an invalid parameter', 5);  
  43.                 break;  
  44.   
  45.             case self::THROW_DEFAULT:  
  46.                 // 抛出默认的异常  
  47.                 throw new Exception('2 isnt allowed as a parameter', 6);  
  48.                 break;  
  49.   
  50.             default:  
  51.                 // 没有异常的情况下,创建一个对象  
  52.                 $this->var = $avalue;  
  53.                 break;  
  54.         }  
  55.     }  
  56. }  
  57.   
  58.   
  59. // 例子 1  
  60. try {  
  61.     $o = new TestException(TestException::THROW_CUSTOM);  
  62. } catch (MyException $e) {      // 捕获异常  
  63.     echo "Caught my exception:<br/>", $e;  
  64.     $e->customFunction();  
  65. } catch (Exception $e) {        // 被忽略  
  66.     echo "Caught Default Exception:<br/>", $e;  
  67. }  
  68. /* 
  69. // 执行后续代码 
  70. var_dump($o); 
  71. echo "<br/>"; 
  72.  
  73.  
  74. // 例子 2 
  75. try { 
  76.     $o = new TestException(TestException::THROW_DEFAULT); 
  77. } catch (MyException $e) {      // 不能匹配异常的种类,被忽略 
  78.     echo "Caught my exception\n", $e; 
  79.     $e->customFunction(); 
  80. } catch (Exception $e) {        // 捕获异常 
  81.     echo "Caught Default Exception\n", $e; 
  82.  
  83. // 执行后续代码 
  84. var_dump($o); 
  85. echo "<br/>"; 
  86.  
  87.  
  88. // 例子 3 
  89. try { 
  90.     $o = new TestException(TestException::THROW_CUSTOM); 
  91. } catch (Exception $e) {        // 捕获异常 
  92.     echo "Default Exception caught\n", $e; 
  93.  
  94. // 执行后续代码 
  95. var_dump($o); 
  96. echo "<br/>"; 
  97.  
  98.  
  99. // 例子 4 
  100. try { 
  101.     $o = new TestException(); 
  102. } catch (Exception $e) {        // 没有异常,被忽略 
  103.     echo "Default Exception caught\n", $e; 
  104. */  
  105.   
  106. // 执行后续代码  
  107. var_dump($o);  
  108. echo "<br/>";  
  109. ?>  
posted @ 2016-12-29 11:24  天涯海角路  阅读(129)  评论(0)    收藏  举报