PHP的错误和异常处理

错误处理


错误报告级别

         如果希望在php脚本中,将某个级别的错误消息报告给他,则必须在配置文件php.ini中,将display_errors指令的值设置为On,开启输出错误报告的功能。也可以在php脚本中调用ini_set()函数,动态配置文件php.ini中的某个指令。

         如果display_error被启动,就会显示满足已设置的错误级别的所有错误报告。当用户在访问网站时,看到现实的这些消息不仅会感到迷惑,而且还可能会更过多地泄露有关服务器的信息,是服务器变得不安全。
调整错误报告级别
         调整错误报告的级别实现,可以通过以下两种方法设置错误报告级别:
  • 可以通过在配置文件php.ini中,修改配置指令error_reporting的值,修改成功后重新启动Web服务器,则每个PHP脚本都可以按调整后的错误报告。下面是修改php.ini配置文件的示例。列出几种为error_reporting指令设置不同级别的值的方式,可以把位运算符[&(与)、|(或)、~(非)]和错误级别常量一起使用。
1
2
3
4
5
6
;可以抛出任何非注意的错误,默认值
error_reporting = E_ALL &~ E_NOTICE
;只考虑致命的运行时错误、解析错误和核心错误
error_reporting = E_ERROE | E_PARSE | E_CORE_ERROR
;报告除用户导致的错误之外的所有错误
error_reporting = E_ALL &~(E_USER_ERROR | E_USER_WARNING |E_USER_NOTICE)
  • 或者在php脚本中使用error_reporting()函数,基于各个脚本来调整这种行为。这个函数用于确定php应该在特定的页面内报告哪些类型的错误。该函数获取一个数字或错误级别常量作为参数。
1
2
3
error_reporting(0);                //设置为0会完全关闭错误报告
error_reporting(E_ALL);            //将会向PHP报告发生的每个错误
error_reporting(E_ALL & ~ E_NOTICE); //可以抛出任何非注意的错误报告
其他配置指令
使用trigger_error()函数来替代die()
         die()等同于exit(),两者如果执行都会终止PHP程序,而且可以在退出程序之前输出一些错误报告。trigger_error()则可以生成一个用户警告来代替,是程序更具有灵活性。
自定义错误处理
         通常使用set_error_handler()函数去设置用户自定义的错误处理函数,该函数用于创建运行时期间的用户自己的错误处理方法,返回就的错误处理程序,若失败,则返回null。该函数有两个参数,其中第一个参数是必选的,需要一个回调函数,规定发生错误时运行的函数。这个回调函数一定要声明4个参数,否则无效,按顺序分别是是否存在错误、错误信息、错误文件和错误行号。set_error_handler()函数的第二个参数是可选的,规定在哪个错误报告级别会显示用户定义的错误。默认是"E_ALL"。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php
     error_reporting (0);                 //屏蔽程序中的错误
     
     /**
         定义Error_Handler函数,作为set_error_handler()函数的第一个参数"回调"
         @param  int     $error_level        错误级别
         @param  string  $error_message  错误信息
         @param  string  $file           错误所在文件
         @param  int     $lin                错误所在行数
     */
     function error_handler( $error_level , $error_message , $file , $line ) {
         $EXIT = FALSE;
         switch ( $error_level ) {
             //提醒级别
             case E_NOTICE:
             case E_USER_NOTICE;
                 $error_type = 'Notice' ;
                 break ;
                 
             //警告级别
             case E_WARNING:
             case E_USER_WARNING:
                 $error_type = 'Warning' ;
                 break ;
             
             //错误级别
             case E_ERROR:
             case E_USER_ERROR:
                 $error_type = 'Fatal Error' ;
                 $EXIT = TRUE;
                 break ;
                 
             //其他末知错误
             default :
                 $error_type = 'Unknown' ;
                 $EXIT = TRUE;
                 break ;
         }
         
         //直接打印错误信息, 也可以写文件,写数据库,反正错误信息都在这,任你发落
         printf ( "<font color='#FF0000'><b>%s</b></font>: %s in <b>%s</b> on line <b>%d</b><br>\n" , $error_type , $error_message , $file , $line );
         
         //如果错误影响到程序的正常执行,跳转到友好的错误提示页面
         if (TRUE == $EXIT ) {
             echo '<script>location = "err.html"; </script>' ;
         }
     }
     
     //这个才是关键点, 把错误的处理交给error_handler()
     set_error_handler( 'error_handler' );
     
     //使用末定义的变量要报 notice 的
     echo $novar ;
     
     //除以0要报警告的
     echo 3/0;
     
     //自定义一个错误
     trigger_error( 'Trigger a fatal error' , E_USER_ERROR);
  • 系统直接报Fital Error这个方法是捕获不到的,遇到这种错误是必须解决的,所以系统会直接终止程序运行。
  • E_ERROR、E_PARSE、E_CORE_ERROR、ERROR_WARNING/E_COMPILE_ERROR、ERROR_COMPILE_WARNING是不会被这个句柄处理的,也就是会用原始的方式显示出来。不过出现这些错误都是编译或PHP内核错误,在通常情况下不会发生。
  • 使用set_error_handler()后,error_reporting()将会失效。也就是所有的错误都会交给自定义的函数处理。
写错误日志
  1、使用指定的文件记录错误报告日志

       如果使用自己指定的文件记录错误日志,一定要确保将这个文件存放在文档目录之外,以减少遭到攻击的可能。并且该文件一定要让PHP脚本的执行用户具有写权限。假设在linux操作系统中,将/usr/local/目录下的config文件作为错误日志文件,并设置Web服务器进程用户具有写的权限。然后在php的配置文件中,将error_log指令的值设置为这个错误日志文件的绝对路径。需要对php.ini中的配置指令做如下修改:

1
2
3
4
5
6
7
8
9
10
;将会向php报告发生的每个错误
error_reporting = E_ALL
;不显示满足上条指令所定义规则的所有错误报告
display_errors = Off
;决定日志语句记录的位置
log_errors = On
;设置每个日志想的最大长度
log_errors_max_len = 1024
;指定产生的错误报告写入的日志文件位置
error_log = /usr/local/error.log

        还可以使用php中的error_log()函数,送出一个用户自定义的错误信息。

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

        第一个参数:必选项,即为要送出的错误信息。

        第二个参数:为整数值,0表示送到操作系统的日志中;1则使用PHP的Mail()函数,发送信息到某Email地址处,第四个参数也会用到;2则将错误信息送到TCP服务器中,此时第三个参数destination表示目的地ip及Port;3则将信息存到文件destination中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php  
     if(!Ora_Logon($username, $password)){  
         //将错误消息写入到操作系统日志中
         error_log("Oracle数据库不可用!", 0);         
     }
     
     if(!($foo=allocate_new_foo()){
         //发送到管理员邮箱中
         error_log("出现大麻烦了!", 1, "webmaster@www.mydomain.com");  
     }
     
     //发送到本机对应5000端口的服务器中
     error_log("搞砸了!",   2,   "localhost:5000");    
     //发送到指定的文件中
     error_log("搞砸了!",   3,   "/usr/local/errors.log"); 

2、错误信息记录到操作系统的日志里

        

1
2
3
4
5
6
7
8
9
10
;将会向php报告发生的每个错误
error_reporting = E_ALL
;不显示满足上条指令所定义规则的所有错误报告
display_errors = Off
;决定日志语句记录的位置
log_erros = On
;设置每个日志项的最大长度
log_errors_max_len = 1024
;指定产生的错误报告写入操作系统的日志里
error_log = syslog

php还允许想系统syslog中发送定制的消息,php为这个特性提供了需要一起使用的4个专用函数。

  • define_syslog_variables()

        使用openlog()、syslog()及closelog()三个函数之前必须先调用该函数,因为在调用该函数时,他会根据现在的系统环境为下面三个函数初使用化一些必需的常量。

  • openlog()

        打开一个和当前系统中日志器的连接,为向系统插入日志消息做好准备。并将提供的第一个字符串参数插入到每个日志消息中,该函数还需要指定两个将在日志上下文使用的参数。

  • syslog()

       该函数向系统日志中发送一个定制消息。需要两个必选参数,第个参数通过指定一个常量定制消息的优先级。第二个参数则是像系统日志中发送定制的消息,需要提供一个消息字符串,也可以是php引擎在运行时提供的错误字符串。

  • closelog()
         该函数在向系统日志中发送完成定制消息以后调用,关闭由openlog()函数打开的日志连接。

1
2
3
4
5
6
7
<?php
     define_syslog_variables();
     
     openlog( "PHP5" , LOG_PID , LOG_USER);
     syslog(LOG_WARNING, "警告报告向syslog中发送的演示,警告时间:" . date ( "Y/m/d H:i:s" ));
     
     closelog ();

异常处理

异常处理实现

        在php中,异常必须手动抛出。throw关键字将触发异常处理机制,他是一个语言结构,而不是一个函数,但必须给它传递一个对象作为值。如果在try语句中游艺场对象被抛出,改代码块不会再继续向下执行,而直接转到catch中执行。并传给catch代码块一个对象,也可以理解为被catch代码块不活的对象,其实就是导致异常常被throw语句抛出的对象。

扩展php那只的异常处理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
/* 自定义的一个异常处理类 ,但必须是扩展内异常处理类的子类  */
class MyException extends Exception{
     //重定义构造器是第一个参数message变为必须被指定的属性
     public function __construct( $message , $code =0){
         //可以在这里定义一些自己的代码
         //建议同时调用parent::construct()来检查所有的变量是否已被赋值
         parent::__construct( $message , $code );
     }
     
     //重写父类方法,自定义字符串输出的样式
     public function __toString(){
         return __CLASS__ . ":[" . $this ->code. "]" . $this ->message. "<br/>" ;
     }
     
     //为这个异常自定义一个处理方法
     public function customFunction(){
         echo "按自定义的方法处理出现的这个类型的异常<br/>" ;
     }
     
}
 
try {
     $error = "允许抛出这个错误" ;
     throw new MyException( $error );
     echo 'Never executed' ;
} catch (MyException $e ) {
     echo '捕获异常:' . $e ;
     $e ->customFunction();
}
echo "你好!" ;

捕获多个异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php
     /* 自定义的一个异常处理类,但必须是扩展内异常处理类的子类 */
     class MyException extends Exception{
         //重定义构造器使第一个参数 message 变为必须被指定的属性
         public function __construct( $message , $code =0){
             //可以在这里定义一些自己的代码
             //建议同时调用 parent::construct()来检查所有的变量是否已被赋值
             parent::__construct( $message , $code );
         }
         //重写父类中继承过来的方法,自定义字符串输出的样式
         public function __toString() {
             return __CLASS__ . ":[" . $this ->code. "]:" . $this ->message. "<br>" ;
         }
 
         //为这个异常自定义一个处理方法
         public function customFunction() {
             echo "按自定义的方法处理出现的这个类型的异常" ;
         }
     }
     
     /* 创建一个用于测试自定义扩展的异常类MyException */
     class TestException {
         public $var ;                                        //用来判断对象是否创建成功的成员属性
 
         function __construct( $value =0) {                    //通过构造方法的传值决定抛出的异常
             switch ( $value ){                                 //对传入的值进行选择性的判断
                 case 1:                                     //传入参数1,则抛出自定义的异常对象
                     throw new MyException( "传入的值“1” 是一个无效的参数" , 5); break ;
                 case 2:                                     //传入参数2,则抛出PHP内置的异常对象
                     throw new Exception( "传入的值“2”不允许作为一个参数" , 6); break ;
                 default :                                    //传入参数合法,则不抛出异常
                     $this -> var = $value ;   break ;              //为对象中的成员属性赋值
                     
             }
         }
     }
     
     /* 示例1,在没有异常时,程序正常执行,try中的代码全部执行并不会执行任何catch区块 */
     try {
         $testObj = new TestException();                     //使用默认参数创建异常的测试类对象
         echo "***********<br>" ;                               //没有抛出异常这条语句就会正常执行
     } catch (MyException $e ){                                 //捕获用户自定义的异常区块
         echo "捕获自定义的异常:$e <br>" ;                  //按自定义的方式输出异常消息
         $e ->customFunction();                                //可以调用自定义的异常处理方法
     } catch (Exception $e ) {                                  //捕获PHP内置的异常处理类的对象
         echo "捕获默认的异常:" . $e ->getMessage(). "<br>" ;    //输出异常消息
     }  
     var_dump( $testObj );          //判断对象是否创建成功,如果没有任何异常,则创建成功
 
     /* 示例2,抛出自定义的异常,并通过自定义的异常处理类捕获这个异常并处理 */
     try {   
         $testObj1 = new TestException(1);                    //传1时,抛出自定义异常
         echo "***********<br>" ;                                //这个语句不会被执行
     } catch (MyException $e ){                                  //这个catch区块中的代码将被执行
         echo "捕获自定义的异常:$e <br>" ;
         $e ->customFunction();
     } catch (Exception $e ) {                                  //这个catch区块不会执行
         echo "捕获默认的异常:" . $e ->getMessage(). "<br>" ;
     }  
     var_dump( $testObj1 );                                    //有异常产生,这个对象没有创建成功
 
     /* 示例2,抛出内置的异常,并通过自定义的异常处理类捕获这个异常并处理 */
     try {
         $testObj2 = new TestException(2);                   //传入2时,抛出内置异常
         echo "***********<br>" ;                           //这个语句不会被执行
     } catch (MyException $e ){                                 //这个catch区块不会执行
         echo "捕获自定义的异常:$e <br>" ;
         $e ->customFunction();
     } catch (Exception $e ) {                                  //这个catch区块中的代码将被执行
         echo "捕获默认的异常:" . $e ->getMessage(). "<br>" ;
     }  
     var_dump( $testObj2 );                                    //有异常产生,这个对象没有创建成功


错误查询

error_get_last():

        函数获取最后发生的错误。 

        该函数以数组的形式返回最后发生的错误。 

        返回的数组包含 4 个键和值: 

  • type:错误类型。
  • message:错误消息。
  • file:发生错误所在的文件。
  • line:发生错误所在的行。

        


        







转载于:https://www.cnblogs.com/staven/p/5be088084fdf38af00a380dd41137c0b.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值