注册错误和异常处理机制有三个PHP函数需要学习

1. register_shutdown_function('Bootstrap\Library\Frame::fatalError');

2. set_error_handler('Bootstrap\Library\Frame::appError');

3. set_exception_handler('Bootstrap\Library\Frame::appException');

1.register_shutdown_function

定义:该函数是来注册一个会在PHP中止时执行的函数

参数说明:

void register_shutdown_function ( callable $callback [, mixed $parameter [, mixed $... ]] )  

注册一个 callback ,它会在脚本执行完成或者 exit() 后被调用。

callback:待注册的中止回调

parameter:可以通过传入额外的参数来将参数传给中止函数

PHP终止情况有三种

执行完成

<?php
function test()
{
echo '这个是中止方法test的输出';
} register_shutdown_function('test'); echo 'before' . PHP_EOL; // => before
// => 这个是中止方法test的输出

注意输出的顺序,等执行完成了之后才会去执行register_shutdown_function的中止方法test  

exit/die导致的中止

<?php
function test()
{
echo '这个是中止方法test的输出';
} register_shutdown_function('test'); echo 'before' . PHP_EOL;
exit();
echo 'after' . PHP_EOL; // => before
// => 这个是中止方法test的输出

后面的after并没有输出,即exit或者是die方法导致提前中止。

发生致命错误中止

<?php
function test()
{
echo '这个是中止方法test的输出';
} register_shutdown_function('test'); echo 'before' . PHP_EOL; // 这里会发生致命错误
$a = new a(); echo 'after' . PHP_EOL; // => before
// => Fatal error: Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\test.php on line 12
// => Error: Class 'a' not found in D:\laragon\www\php_book\test.php on line 12
// => Call Stack:
// => 0.0020 360760 1. {main}() D:\laragon\www\php_book\test.php:0
// => 这个是中止方法test的输出

后面的after也是没有输出,致命错误导致提前中止了。

参数:第一个参数支持以数组的形式来调用类中的方法,第二个以及后面的参数都是可以当做额外的参数传给中止方法。

<?php  

class Shutdown
{
public function stop()
{
echo "这个是stop方法的输出";
}
} // 当PHP终止的时候(执行完成或者是遇到致命错误中止的时候)会调用new Shutdown的stop方法
register_shutdown_function([new Shutdown(), 'stop']); // 将因为致命错误而中止
$a = new a(); // 这一句并没有执行,也没有输出
echo '必须终止';

也可以在类中执行:

<?php  

class TestDemo {
public function __construct()
{
register_shutdown_function([$this, "f"], "hello");
} public function f($str)
{
echo "class TestDemo->f():" . $str;
}
} $demo = new TestDemo();
echo 'before' . PHP_EOL; /**
运行:
before
class TestDemo->f():hello
*/
可以多次调用 register_shutdown_function,这些被注册的回调会按照他们注册时的顺序被依次调用。

不过注意的是,如果在第一个注册的中止方法里面调用exit方法或者是die方法的话,那么其他注册的中止回调也不会被调用。

代码:

<?php
/**
* 可以多次调用 register_shutdown_function,这些被注册的回调会按照他们注册时的顺序被依次调用。
* 注意:如果你在f方法(第一个注册的方法)里面调用exit方法或者是die方法的话,那么其他注册的中止回调也不会被调用
*/ /**
* @param $str
*/
function f($str) {
echo $str . PHP_EOL; // 如果下面调用exit方法或者是die方法的话,其他注册的中止回调不会被调用
// exit();
} // 注册第一个中止回调f方法
register_shutdown_function("f", "hello"); class TestDemo {
public function __construct()
{
register_shutdown_function([$this, "f"], "hello");
} public function f($str)
{
echo "class TestDemo->f():" . $str;
}
} $demo = new TestDemo();
echo 'before' . PHP_EOL; /**
运行:
before
hello
class TestDemo->f():hello 注意:如果f方法里面调用了exit或者是die的话,那么最后的class TestDemo->f():hello不会输出
*/
该函数的作用:
  • 析构函数:在PHP4的时候,由于类不支持析构函数,所以这个函数经常用来模拟实现析构函数
  • 致命错误的处理:使用该函数可以用来捕获致命错误并且在发生致命错误后恢复流程处理

代码如下:

<?php
/**
* register_shutdown_function,注册一个会在php中止时执行的函数,中止的情况包括发生致命错误、die之后、exit之后、执行完成之后都会调用register_shutdown_function里面的函数
* Created by PhpStorm.
* User: Administrator
* Date: 2017/7/15
* Time: 17:41
*/ class Shutdown
{
public function stop()
{
echo 'Begin.' . PHP_EOL;
// 如果有发生错误(所有的错误,包括致命和非致命)的话,获取最后发生的错误
if (error_get_last()) {
print_r(error_get_last());
} // ToDo:发生致命错误后恢复流程处理 // 中止后面的所有处理
die('Stop.');
}
} // 当PHP终止的时候(执行完成或者是遇到致命错误中止的时候)会调用new Shutdown的stop方法
register_shutdown_function([new Shutdown(), 'stop']); // 将因为致命错误而中止
$a = new a(); // 这一句并没有执行,也没有输出
echo '必须终止';
Fatal error: Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php on line 31  

Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php on line 31  

Call Stack:
0.0060 362712 1. {main}() D:\laragon\www\php_book\1_23_register_shutdown.php:0 Begin.
Array
(
[type] => 1
[message] => Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php:31
Stack trace:
#0 {main}
thrown
[file] => D:\laragon\www\php_book\1_23_register_shutdown.php
[line] => 31
)
Stop.

注意:PHP7中新增了Throwable异常类,这个类可以捕获致命错误,即可以使用try...catch(Throwable $e)来捕获致命错误,代码如下:

<?php  

try {
// 将因为致命错误而中止
$a = new a(); // 这一句并没有执行,也没有输出
echo 'end';
} catch (Throwable $e) {
print_r($e);
echo $e->getMessage();
}

运行:

Error Object
(
[message:protected] => Class 'a' not found
[string:Error:private] =>
[code:protected] => 0
[file:protected] => C:\laragon\www\php_book\throwable.php
[line:protected] => 5
[trace:Error:private] => Array
(
) [previous:Error:private] =>
[xdebug_message] =>
Error: Class 'a' not found in C:\laragon\www\php_book\throwable.php on line 5 Call Stack:
0.0000 349856 1. {main}() C:\laragon\www\php_book\throwable.php:0 )
Class 'a' not found
这样的话,PHP7中使用Throwable来捕获的话比使用register_shutdown_function这个函数来得更方便,也更推荐Throwable。
注意:Error类也是可以捕获到致命错误,不过Error只能捕获致命错误,不能捕获异常Exception,而Throwable是可以捕获到错误和异常的,所以更推荐。
 
总结:register_shutdown_function这个函数主要是用在处理致命错误的后续处理上(PHP7更推荐使用Throwable来处理致命错误),不过缺点也很明显,只能处理致命错误Fatal error,其他的错误包括最高错误Parse error也是没办法处理的。
 

 

2.set_error_handler

通过 set_error_handler() 函数设置用户自定义的错误处理程序,然后触发错误(通过 trigger_error()):

<?php
// 用户定义的错误处理函数
function myErrorHandler($errno, $errstr, $errfile, $errline) {
echo "<b>Custom error:</b> [$errno] $errstr<br>";
echo " Error on line $errline in $errfile<br>";
} // 设置用户定义的错误处理函数
set_error_handler("myErrorHandler"); $test=2; // 触发错误
if ($test>1) {
trigger_error("A custom error has been triggered");
}
?>

以上代码的输出类似这样:

Custom error: [1024] A custom error has been triggered
Error on line 14 in C:\webfolder\test.php

定义和用法

set_error_handler() 函数设置用户定义的错误处理函数。

注释:如果使用该函数,会绕过标准 PHP 错误处理程序,同时如果必要,用户定义错误程序通过 die() 终止脚本。

注释:如果错误发生在脚本执行之前(比如文件上传时),将不会调用自定义的错误处理程序因为它尚未在那时注册。

语法

set_error_handler(errorhandler,E_ALL|E_STRICT);
参数 描述
errorhandler 必需。规定用户错误处理函数的名称。
E_ALL|E_STRICT 可选。规定显示何种错误报告级别的用户定义错误。默认是 "E_ALL"。

技术细节

返回值: 包含之前定义的错误处理程序的字符串。
PHP 版本: 4.0.1+
PHP 更新日志:

PHP 5.5:参数 errorhandler 现在接受 NULL

PHP 5.2: 错误处理程序必须返回 FALSE 来显示 $php_errormsg。

3.set_exception_handler

设置用户定义的异常处理函数:

<?php
// 用户定义的异常处理函数
function myException($exception) {
echo "<b>Exception:</b> ", $exception->getMessage();
} // 设置用户定义的异常处理函数
set_exception_handler("myException"); // 抛出异常
throw new Exception("Uncaught exception occurred!");
?>

以上代码的输出类似这样:

Exception: Uncaught exception occurred!

定义和用法

set_exception_handler() 函数设置用户定义的异常处理函数。

脚本会在此异常处理程序被调用后停止执行。

语法

set_exception_handler(exceptionhandler);
参数 描述
exceptionhandler

必需。规定当一个未捕获的异常发生时所调用函数的名称。

注释:也可以传递一个 NULL 值用于重置异常处理函数为默认值。

技术细节

返回值:

返回包含之前定义的异常处理程序的名称的字符串,或者在错误时返回 NULL。

如果之前没有定义一个错误处理程序,也会返回 NULL。

如果参数使用了 NULL,重置处理程序为默认状态,并且会返回一个 TRUE。

PHP 版本: 5.0+
PHP 更新日志:

PHP 7.0.0:传递到 exception_handler 中的参数类型从 Exception 更改为 Throwable。

PHP 5.5:之前,如果传递 NULL,该函数返回 TRUE。从 PHP 5.5 起返回之前的处理程序。

PHP 注册错误和异常处理机制的更多相关文章

  1. ThinkPHP5.0源码学习之注册错误和异常处理机制

    在base.php文件中,用一句代码\think\Error::register();实现错误和异常处理机制的注册. // 注册错误和异常处理机制 \think\Error::register(); ...

  2. 【Go语言】错误与异常处理机制

    ①error接口 Go语言中的error类型实际上是抽象了Error()方法的error接口 type error interface { Error() string } Go语言使用该接口进行标准 ...

  3. php5和php7的异常处理机制 ----thinkphp5 异常处理的分析

    1.php异常和错误 在其他语言中,异常和错误是有区别的,但是PHP,遇见自身错误时,会触发一个错误,而不是跑出异常.并且,php大部分情况,都会触发错误,终止程序执行,在php5中,try catc ...

  4. php错误处理和php异常处理机制

    php错误处理  当我们开发程序时,有时候程序出现了问题,我们就可以用以下几种办法找出错误.  开发阶段:开发时输出所有的错误报告,有利于我们进行程序调试  运行阶段:我们不要让程序输出任何一种错误报 ...

  5. 再谈PHP错误与异常处理

    博客好久没有更新了,实在惭愧,最近在忙人生大事,哈哈!这段时间没有看什么新的东西,结合项目中遇到的PHP异常处理问题,我又重新梳理了之前模糊的概念,希望对大家理解PHP异常处理有所帮助. 请一定要注意 ...

  6. Spring Cloud微服务如何设计异常处理机制?

    导读 今天和大家聊一下在采用Spring Cloud进行微服务架构设计时,微服务之间调用时异常处理机制应该如何设计的问题.我们知道在进行微服务架构设计时,一个微服务一般来说不可避免地会同时面向内部和外 ...

  7. 2018/05/02 PHP 之错误与异常处理

    在学习中,越学习越觉得自己基础薄弱. 在平常工作中,对于某些错误处理感觉不知道怎么下手,于是决定重新再整理一下. 强烈推荐这篇文章,真的感觉学习到了很多. 部分引用::再谈PHP错误与异常处理 -- ...

  8. SpringMVC异常处理机制

    SpringMVC异常处理机制 springMVC会将所有在doDispatch方法中的异常捕获,然后处理.无法处理的异常会抛出给容器处理. 在doDispatch()中调用processDispat ...

  9. C++ 异常处理机制的实现

    http://blog.jobbole.com/103925/ 本文深入讨论了VC++编译器异常处理的实现机制.附件源代码包含了一个VC++的异常处理库. 下载源代码 – 19 Kb 介绍 相对于传统 ...

随机推荐

  1. ng4.0 生命周期

    名称 时机 接口 范围 ngOnChanges 当被绑定的输入属性的值发生变化时调用,首次调用一定会发生在 ngOnInit之前. OnChanges 指令和组件 ngOnInit 在第一轮 ngOn ...

  2. Elasticsearch学习之配置小记

    基于 elasticsearch 1.4.4 版本.安装方式为RPM安装.所有涉及路径需根据实际情况来设置判断. 0x01 内存调整 调整ES内存分配有多种方式,建议调整 /etc/sysconfig ...

  3. electron 主进程,和渲染进程的通信

    ipcMain https://electronjs.org/docs/api/ipc-main 当在主进程中使用时,它处理从渲染器进程(网页)发送出来的异步和同步信息, 当然也有可能从主进程向渲染进 ...

  4. 如何将MP3录音转文字

    相信很多人都有电话录音的习惯,因为这样可以记录下很多重要的信息.那么当我们通过录音将一些重要的信息记录下来后,我们应该怎样将这些录音文件转换成文字进行记录呢?下面我们就一起来看一下吧. 操作步骤: 步 ...

  5. 洛谷P1403 约数研究【思维】

    题目:https://www.luogu.org/problemnew/show/P1403 题意: 定义$f(n)$为n的因子个数.给定一个数n,求$f(1)$到$f(n)$之和. 思路: 最直接的 ...

  6. 专访姚冬:All-in-One,智能时代下企业需要更快速的变革

    2017年,msup将咨询服务列入公司发展战略目标,并邀请前IBM大中华区技术总监姚冬成为咨询合伙人.近一年来,msup在咨询服务方面持续发力,与包括百度.平安科技.用友等在内的大型公司形成企业合作联 ...

  7. 线段树||BZOJ1593: [Usaco2008 Feb]Hotel 旅馆||Luogu P2894 [USACO08FEB]酒店Hotel

    题面:P2894 [USACO08FEB]酒店Hotel 题解:和基础的线段树操作差别不是很大,就是在传统的线段树基础上多维护一段区间最长的合法前驱(h_),最长合法后驱(t_),一段中最长的合法区间 ...

  8. window10装机 nvem简介,针对于 联想R720系列

    1.nvem格式的硬盘比较新,传统的老毛桃,大白菜,并不能有效使用. 2.对于镜像类 goust类,仍然具备 硬盘兼容性差(对于gpt,MAR,uefi并不够智能)成功率极低,容易丢失一些关键文件,造 ...

  9. CSS 小技巧

    CSS 小技巧 一.边框内圆角 我们在设计例如按钮等控件的时候,会遇到这样的设计:只有内侧有圆角,而边框或者描边的四个角还是保持直角的形状,用以下代码可以轻松的实现. #wrapper { width ...

  10. Python:if __name__ == '__main__'

    简介: __name__是当前模块名,当模块被直接运行时模块名为_main_,也就是当前的模块,当模块被导入时,模块名就不是__main__,即代码将不会执行. 关于代码if __name__ == ...