异常处理主要由try、catch、finally三个关键字来实现。文中所有代码在PHP7环境下一切正常,PHP5及以下版本,部分代码并不能达到预期效果。废话少说,进入正题。

抛出、捕获异常

throw new Exception('异常信息');

执行上面的代码,输出如下

Fatal error: Uncaught Exception: 异常信息 in D:\WWW\demo\index.php:2 Stack trace: #0 {main} thrown in D:\WWW\demo\index.php on line 2

捕获这个异常

try {
    throw new Exception('异常信息', 1);
} catch (Exception $e) {
    print_r($e);
}

这是一个典型的异常捕获,打印Exception对象$e

Exception Object
(
    [message:protected] => 异常信息
    [string:Exception:private] => 
    [code:protected] => 1
    [file:protected] => D:\WWW\demo\index.php
    [line:protected] => 3
    [trace:Exception:private] => Array
        (
        )

    [previous:Exception:private] => 
)

可以看到,这里包含了异常的详细信息。我们可以针对这个异常在catch代码块里进行下一步处理,比如让信息重新排版显示

try {
    throw new Exception('异常信息', 1);
} catch (Exception $e) {
    echo '信息:' . $e->getMessage() . "\r\n";
    echo '位置:' . $e->getFile() . "\r\n";
    echo '行:' . $e->getLine() . "\r\n";
    echo 'code:' . $e->getCode();
}

再次执行上面代码,结果如下

信息:异常信息
位置:D:\WWW\demo\index.php
行:3
code:1

自定义异常类

新建两个自定义异常类MyException、DemoException,并且都继承自Exception基类,分别都定义一个handler方法用来处理异常信息。

MyException

namespace exception;

class MyException extends \Exception {

    public function handler() {
        echo '信息:' . $this->getMessage() . "\r\n";
        echo '位置:' . $this->getFile() . "\r\n";
        echo '行:' . $this->getLine() . "\r\n";
        echo 'code:' . $this->getCode();
    }
}

DemoException

namespace exception;

class DemoException extends \Exception {

    public function handler() {
        echo '我是DemoException异常,信息:' . $this->getMessage();
    }
}

改造代码

use exception\MyException;
use exception\DemoException;
require 'exception/MyException.php';
require 'exception/DemoException.php';

try {
    throw new DemoException('异常信息', 1);
} catch (MyException $e) {
    $e->handler();
} catch (DemoException $e) {
    $e->handler();
} catch (Exception $e) {
    echo $e->getMessage();
}

执行上面代码,结果如下

我是DemoException异常,信息:异常信息

因此,在这里得出一个结论

在捕获异常时,会根据具体的异常类型去执行catch代码块,如果没有找到到对应的类型,则会视为Exception异常进行处理。

set_exception_handle函数

关于set_exception_handle函数,部分手册原文

set_exception_handler — 设置用户自定义的异常处理函数,用于没有用 try/catch 块来捕获的异常。
callable set_exception_handler ( callable $exception_handler )

手册中提到,set_exception_handle函数用于处理没有用try/catch块捕获的异常。抛出一个异常,不捕获

function MyException($e) {
    echo '信息:' . $e->getMessage() . "\r\n";
    echo '位置:' . $e->getFile() . "\r\n";
    echo '行:' . $e->getLine() . "\r\n";
    echo 'code:' . $e->getCode();
}
set_exception_handler('MyException');
throw new Exception('异常信息', 1);

执行上面的代码,结果如下

信息:异常信息
位置:D:\WWW\demo\index.php
行:9
code:1

这个异常已经由MyException处理,与之前捕获到的信息相同。当然了,set_exception_handler函数的参数为callable类型,所以也支持出入匿名函数、类方法。对MyException类稍加改动

namespace exception;

class MyException extends \Exception {

    public function handler($e) {
        echo '信息:' . $e->getMessage() . "\r\n";
        echo '位置:' . $e->getFile() . "\r\n";
        echo '行:' . $e->getLine() . "\r\n";
        echo 'code:' . $e->getCode();
    }
}

然后设置自定义异常处理也是可行的

set_exception_handler([(new MyException()), 'handler']);

finally

finally代码块不管程序有没有出现异常都会执行。

try {
    throw new Exception('异常信息', 1);
} catch (Exception $e) {
    print_r($e);
} finally {
    echo 'Hello';
}

这种情况下,try代码块中不管有没有出现异常,Hello都会被输出。finally代码块中的代码总是被执行。

标签: php, 异常处理

添加新评论