为何register_shutdown_function()在PHP命名空间中无法正常工作?
问题原因及解决办法
你的问题
我写了这段PHP代码:
<?php namespace joe; function shutdown() { if(is_null($e = error_get_last()) === false) { mail('bili@web.de', 'Error from auto_prepend', print_r($e, true)); } }; register_shutdown_function('shutdown'); ...
运行时出现错误:
Warning: register_shutdown_function(): Invalid shutdown callback 'shutdown' passed in /www/...
但删除命名空间后代码就能正常运行,请问这是什么原因?
原因分析
这完全是PHP命名空间的作用域在搞鬼!当你在joe命名空间里定义shutdown函数时,这个函数的完整标识是joe\shutdown,它属于joe这个命名空间,而不是全局空间。
但你调用register_shutdown_function('shutdown')时,PHP会默认去全局命名空间找这个函数——可全局空间里根本没有叫shutdown的函数,自然就抛出"无效回调"的警告了。
而删除命名空间后,函数会自动归到全局命名空间,这时候'shutdown'就能被正确匹配到,代码也就正常运行了。
修复方案
有三种简单的方式可以解决这个问题:
- 直接使用完全限定函数名
把回调参数写成命名空间+函数名的完整形式:
register_shutdown_function('joe\shutdown');
- 用
__NAMESPACE__动态拼接
如果不想硬编码命名空间名称,用魔术常量__NAMESPACE__来动态生成完整标识:
register_shutdown_function(__NAMESPACE__ . '\shutdown');
- 使用匿名闭包
闭包会自动继承当前的命名空间上下文,直接在闭包里调用shutdown即可:
register_shutdown_function(function() { shutdown(); });
这三种方法都能完美解决你的问题,选哪种全看你的代码习惯~
内容的提问来源于stack exchange,提问作者hamburger
相关产品推荐
相关产品推荐

