系统的总结PHP中的错误与异常

本文对比了PHP与Java在错误处理方面的不同,介绍了PHP中错误与异常的关系,并提供了自定义错误与异常处理的方法。

写过一段时间的PHP代码的都可能会感觉自己在开发过程中基本没用过PHP中的异常,我也一样。最近,类比了一下Java中的一些写法以后,发现PHP在代码报错方面和其他的语言有很大的区别。首先,当出现文法错误以后,Java会报异常,而PHP绝大多数情况下会报错误。既然如此,那么PHP中的异常是来干嘛的那?PHP中的错误和异常的区别在哪那?这里就总结一下。

(1):当PHP中出现自身错误以后,绝大多数情况下,会抛出一个错误,并不会抛出一个异常。在少数情况下,会同时抛出一个错误和一个异常。也就是说PHP中有错误和异常两种错误报告形式。Java等语言针对自身错误,只会抛出异常,也就说java中只有异常一种错误报告形式。这也就说明了,PHP针对错误的设计理念和Java等其他语言是不一样的。想要像Java语言一样,通过异常来处理代码逻辑中不可预料的情况,通常来说是办不到的。看下面的代码:

<?php
        $f = fopen("./test.txt","r");
         //./test.txt是不存在,此时php会抛出一个错误,并不会抛出一个异常
?>复制代码

(2):上面已经说了,PHP绝大情况下并不会主动的抛出异常,但是我们可以自己手动的抛出异常,并进行异常的捕捉。也就是说,如果我们不主动的手动抛出异常,我们也就捕捉不到异常。(手动抛出异常才能捕捉异常的形式和"异常"的思想是背道而驶的)。看下面代码,我们必须自己做检测,发现异常情况以后,手动抛出异常,而不能像java一样,由java解释器自动的来处理。

<?php
    try{
         $num_one = 7;
         $num_two = 0;
         if($num_two == 0){
                  //抛出一个异常
                  throw new Exception("num_two不能为0");
         }
     }catch(Exception $e){
          echo $e->getMessage();
     }
?>复制代码

java中拥有很多的内置异常,当代码出现问题了,java编译器可以主动的抛出异常进行处理。java程序员只需要考虑异常的捕捉以及发生异常后的补救措施。而php程序员需要不断的使用if else 进行数据的判断,手动的抛出异常,再进行处理。

上面理解了PHP中的错误和异常之间的关系以后,我们可以更进一步,看看如何自定义异常与错误。用过框架的都知道,PHP框架一般都会以更直观的方式重写PHP中的异常与错误的处理形式,而不是采用PHP本身的异常与错误处理形式。

(1):使用set_error_handler()来接管PHP本身的错误处理。该函数允许我们自定义错误处理形式。代码如下:

function error_handler($errno,$errstr,$errfile,$errline){
        switch($errno) {
            case 2:
                $error_type = "E_WARNING";
                break;
            case 8:
                $error_type = "E_NOTICE";
                break;
            default:
                $error_type = "";
                break;
        }
        echo $error_type."<br/>";
        echo $errstr."<br/>";
        echo $errfile."<br/>";
        echo $errline."<br/>";
        echo "<pre/>";
        print_r(debug_backtrace());
        die();
}
set_error_handler("error_handler");复制代码

需要注意的是:一旦使用了set_error_handler()函数来接管了php自身的错误处理机制以后,发生错误以后,就会直接调用set_error_handler()中指定的回调函数。并将错误相关的信息,比如说错误行号,文件名等信息传递到该回调函数。其他还需要的注意的设置set_error_handler()函数以后,原先使用的@这个屏蔽错误的语法糖就失去作用了。

(2):另外,看手册会发现,该函数并不会接管所有的错误,Fatal_error,Parse_error等错误类型该函数是接管不了的。Parse_error是解析错误,是php解释器解释阶段发生的错误,我们是不可能接管这个错误的。对于Fatel_error致命错误,我们可以通过register_shutdown_function()函数来进行处理。需要注意的是,这个函数并不能替我们接管错误信息,而是在程序彻底“死掉”之前,执行一下其指定的回调函数。有点类似与PHP类中的析构函数。基本使用如下:

function fatal_error_handler(){  //发生致命错误以后,再执行该函数,所以默认的fatal_error报错信息仍然会暴露出来
       //获取最近的一次的错误
       $last_error = error_get_last();
       if($last_error) {
           echo "<pre/>";
           print_r($last_error);
           print_r(debug_backtrace());
       }
}复制代码

上面代码中的error_get_last()以及debug_backtrace()函数的用法,这里就不赘述了。

(3):对于异常,我们同样可以使用set_exception_handler()函数来接管php内置的异常处理。使用方法和set_error_handler()函数很接近。

/*
 * 进行异常注册处理
 */
function exception_handler($e){
       echo "异常信息如下<br/>";
       echo $e->getMessage();
}
set_exception_handler("exception_handler");复制代码

使用set_exception_handler()函数来接管内置的异常,除了可以自定义异常以外,还有一个区别。那就是可以随时捕捉到异常。在php默认环境下,手动抛出一个异常,但是不进行异常的捕捉,会报Fatal_error的。

<?php
         if($num==0){
                 throw new Exception("异常信息");
                 //代码执行,报错,因为没有进行异常的捕捉
         }
?>复制代码

(4):在框架中,为了解决专门的问题,一般都会重写Exception类,根据不同情况使用不同的Exception类来进行处理。看下面代码:

<?php
//针对IO异常
class IoException extends  Exception {

    public function __construct($message, $code=0, Exception $previous=null)
    {
        parent::__construct($message, $code, $previous);
    }
}

function exception_handler($e){
       echo "异常信息如下<br/>";
       echo $e->getMessage();
}
set_exception_handler("exception_handler");

if(!function_exists("write")){
      //抛出IO异常
      throw  new IoException("方法write()不存在");
}复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值