register.php,PHP中register_shutdown_function函数的基础介绍与用法详解

前言

最近在看《PHP核心技术与最佳实践》,里面有使用到一个函数,register_shutdown_function,由于之前没有用过该函数,就去查了一下资料,就觉得是个很实用的函数,所以这里写一下这个函数的用法。下面话不多说了,来一起看看详细的介绍吧。

1. 函数说明

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

参数说明:

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

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

callback:待注册的中止回调

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

2. PHP中止的情况

PHP中止的情况有三种:

执行完成

exit/die导致的中止

发生致命错误中止

a. 第一种情况,执行完成

function test()

{

echo '这个是中止方法test的输出';

}

register_shutdown_function('test');

echo 'before' . PHP_EOL;

运行:

before

这个是中止方法test的输出

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

b. 第二种情况,exit/die导致的中止

function test()

{

echo '这个是中止方法test的输出';

}

register_shutdown_function('test');

echo 'before' . PHP_EOL;

exit();

echo 'after' . PHP_EOL;

运行:

before

这个是中止方法test的输出

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

c. 第三种情况,发送致命错误中止

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也是没有输出,致命错误导致提前中止了。

3. 参数

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

class Shutdown

{

public function stop()

{

echo "这个是stop方法的输出";

}

}

// 当PHP终止的时候(执行完成或者是遇到致命错误中止的时候)会调用new Shutdown的stop方法

register_shutdown_function([new Shutdown(), 'stop']);

// 将因为致命错误而中止

$a = new a();

// 这一句并没有执行,也没有输出

echo '必须终止';

也可以在类中执行:

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

*/

4. 同时调用多个

可以多次调用 register_shutdown_function,这些被注册的回调会按照他们注册时的顺序被依次调用。

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

代码:

/**

* 可以多次调用 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不会输出

*/

5. 用处

该函数的作用:

析构函数:在PHP4的时候,由于类不支持析构函数,所以这个函数经常用来模拟实现析构函数

致命错误的处理:使用该函数可以用来捕获致命错误并且在发生致命错误后恢复流程处理

代码如下:

/**

* 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)来捕获致命错误,代码如下:

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是可以捕获到错误和异常的,所以更推荐。

6.巧用register_shutdown_function判断php程序是否执行完

还有一种应用场景就是:要做一个消费队列,因为某条有问题的数据导致致命错误,如果这条数据不处理掉,那么整个队列都会导致瘫痪的状态,这样可以用以下方法来解决。即:如果捕获到有问题的数据导致错误,则在回调函数中将这条数据处理掉就可以了。

php范例参考与解析:

register_shutdown_function('myFun'); //放到最上面,不然如果下面有致命错误,就不会调用myFun了。

$execDone = false; //程序是否成功执行完(默认为false)

/**

********************* 业务逻辑区*************************

*/

$tas = 3;

if($tas == 3)

{

new daixiaorui();

}

/**

********************* 业务逻辑结束*************************

*/

$execDone = true; //由于程序由上至下执行,因此当执行到此后,则证明逻辑没有出现致命的错误。

function myFun()

{

global $execDone;

if($execDone === false)

{

file_put_contents("E:/myMsg.txt", date("Y-m-d H:i:s")."---error: 程序执行出错。\r\n", FILE_APPEND);

/******** 以下可以做一些处理 ********/

}

}

总结

register_shutdown_function这个函数主要是用在处理致命错误的后续处理上(PHP7更推荐使用Throwable来处理致命错误),不过缺点也很明显,只能处理致命错误Fatal error,其他的错误包括最高错误Parse error也是没办法处理的。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值