这篇文章,我们来介绍下如何通过PHP扩展在PHP脚本将要退出前执行代码。我们可以看一段Swoole的协程代码:
1 |
|
执行结果如下:
1 | string(1) "3" |
我们发现,在打印4之后,PHP脚本算是执行完了,这个时候,PHP进程也快要退出了。那为什么还会打印出1和2呢?
因为PHP是一门解释性语言,虽然PHP脚本的代码跑完了,但是PHP命令解释器还没有跑完,自然可以让PHP代码继续跑。所以,实际上,这个代码会这样:
1 |
|
在脚本的最后会调用Event::wait()来等待事件的结束。(而这里的事件就是定时器的事件)
好的,我们现在通过一个小demo来实现这个功能。
首先,我们需要创建PHP扩展的基础骨架。通过ext_skel工具生成:
1 | [root@64fa874bf7d4 ext]# php ext_skel.php --ext register |
然后进入register目录:
1 | [root@64fa874bf7d4 ext]# cd register/ |
替换config.m4为如下内容:
1 | PHP_ARG_ENABLE(register, whether to enable register support, |
然后,我们创建和编写测试脚本:
1 | [root@64fa874bf7d4 register]# touch test.php |
1 |
|
这段脚本只定义了一个test函数,并没有调用。现在我们的任务就是去调用它。
我们开始编写PHP扩展。在文件register.c的PHP_RINIT_FUNCTION里面注册test函数:
1 |
|
这里,我们首先对php_shutdown_function_entry结构进行初始化,php_shutdown_function_entry.arguments的第一个位置填函数的名字。shutdown_function_entry.arg_count填写1,因为函数名字也算做是arguments。初始化完php_shutdown_function_entry之后,我们调用register_user_shutdown_function函数即可注册test函数了。这样,就会在php请求shutdown阶段调用我们注册的函数了。
然后编译、安装扩展:
1 | [root@64fa874bf7d4 register]# phpize && ./configure && make && make install |
然后把扩展在php.ini文件里面进行开启:
1 | ; Enable zlib extension module |
然后执行脚本:
1 | [root@64fa874bf7d4 register]# php test.php |
我们发现,成功的调用了test函数。
这让我想起了我之前面试腾讯的时候,有一道题目,说是如何在每一个PHP函数调用之前,都执行一段代码。这个问题以后补上。