0x00 简单应用
当执行部分可能抛出异常的代码时,catch
可以捕捉到 try
代码段内抛出的异常(前提是 catch
的参数类型和抛出的异常类型相符),类型不符合的异常会继续向上层抛出。比如以下代码:
直接捕获:
function foo() { throw new Exception('hello world' . PHP_EOL); }
try { foo(); } catch (Exception $e) { echo $e->getMessage(); }
|
抛出至上层捕获:
function foo() { throw new RuntimeException(); }
try { try { foo(); } catch (OutOfRangeException $e) { echo 'catch OutOfRangeException'; } } catch (RuntimeException $e) { echo 'catch RuntimeException'; }
|
可以使用多个连续 catch
捕获不同类型的异常,示例如下:
function foo() { if (random_int(0, 1)) { throw new RuntimeException(); } else { throw new OutOfRangeException(); } }
try { foo(); } catch (OutOfRangeException $e) { echo 'catch OutOfRangeException'; } catch (RuntimeException $e) { echo 'catch RuntimeException'; }
|
PHP 7.1 新特性:同一个 catch
可以通过 |
分割异常类型,实现捕获多种异常。示例如下:
function foo() { if (random_int(0, 1)) { throw new RuntimeException('I am RuntimeException'); } else { throw new OutOfRangeException('I am OutOfRangeException'); } }
try { foo(); } catch (OutOfRangeException|RuntimeException $e) { echo $e->getMessage(); }
|
0x01 返回值的注意事项
在没有引入 finally
关键字时,在 try...catch
的中返回值是符合直觉的如下例:
function foo() { try { throw new Exception(); return 1; } catch (Exception $e) { return 2; } }
echo foo();
|
但引入 finally
关键字的代码如下:
function foo() { try { throw new Exception(); return 1; } catch (Exception $e) { return 2; } finally { return 3; } }
echo foo();
|
finally
内的代码是无论是否捕获到异常都会执行的代码,并且当 finally
中存在 return
返回值时,整个try..catch...finally
段的返回值只会是 finally
的返回值。
猜测下例代码输出
$a = 1; function foo(&$a) { try { $a = 2; return $a; } finally { $a = 3; } } echo foo($a); echo $a;
|
输出结果为 23
这说明了finally
即使在 try
或 catch
中执行了 return
也同样会执行。
0x02 Throwable 接口
Throwable
是 PHP 7 新出的一个预定义接口,Error
和 Exception
类都实现了这个接口,也就是说我们现在有能力通过 catch
捕获到 Error
。示例如下:
function foo(int $a): int { return $a; }
try { foo('string'); } catch (Throwable $e) { echo get_class($e); }
|
例子表明了参数类型不符所抛出的 TypeError
错误可以被 catch
捕获。
0x03 全局异常处理函数
官方文档 set_exception_handler 设置一个全局的异常处理函数可以捕获所有没有被 catch
到的异常。使用示例:
set_exception_handler(function (Exception $e) { echo $e->getMessage(); });
function foo() { throw new Exception('nobody catch me'); }
foo();
|
类似的对于错误处理有 set_error_handler 函数。
友情提示:垃圾评论一律封号...