destruct析构函数里操作文件出现的问题
这几天要给后台加一个记录操作日志的功能,可是项目已经开发完了不可能再去改以前的代码了,那有什么快捷的方法呢?
项目使用的ThinkPHP3.23 ,为了方便权限控制,后台控制器结构为:普通控制器 extends pubController ,pubController extends Controller.
所以,可不可以在pubController 里用__destruct 析构函数 记录日志呢?
大家都知道,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。
所以应该没问题咯,1、配置要记录日志的操作 2、读取IP、get、post数据写入库 3.本地测试没问题,搞定。
结果 BU G T
部署到线上之后,ThinkPHP底层报错了:
Fatal error: Uncaught Think\Exception: _STORAGE_WRITE_ERROR_***/Runtime/Data/_fields/表结构缓存文件.php in ***/Runtime/common~runtime.php:1 Stack trace: #0 ***/ThinkPHP/Library/Think/Storage/Driver/File.class.php(48): E('_STORAGE_WRITE_...') #1 [internal function]: Think\Storage\Driver\File->put('***', 'a:9:{i:0;s:2:"i...', 'F') #2 ***/ThinkPHP/Library/Think/Storage.class.php(37): call_user_func_array(Array, Array) #3 ***/hwApp/Runtime/common~runtime.php(1): Think\Storage::__callstatic('put', Array) #4 ***/ThinkPHP/Library/Think/Model.class.php(166): F('***', Array) #5 ***/ThinkPHP/Library/Think/Model.class.php(122): Think\Model->flush() #6 ***/ThinkPHP/Library/Think/Model.class.php(1454): Think\Model->_checkTableInfo() #7 ***/ThinkPHP/Library/Think/Model.class.php(97): Think\Model->db(0, '', true) #8 ***/Runtime/common~runtime.php(1): Think\Model->__construct( in ***/Runtime/common~runtime.php on line 1
咦?啥情况,难道没权限?
chmod -R 777 Runtime
还报错,难道是缓存引起的?
rm -rf Runtime
还报错。
最后在重新看官方对该函数的说明,手册里有一个不太明显的notice:
Note:
析构函数在脚本关闭时调用,此时所有的HTTP头信息已经发出。 脚本关闭时的工作目录有可能和在SAPI(如apache)中时不一样。
<?php
//获取当前工作目录 function __destruct(){
echo getcwd(); //结果为根目录
}
知道了问题所在,怎么解决呢?
1、在__destruct 中使用绝对路径操作文件
2、__destruct 之前比如构造函数内,先获取 getcwd() 工作目录,然后在 __destruct 中使用 chdir($StrPath) 重新设定工作目录。 //暂未测出有其他影响
另:脚本关闭是指:代码执行完毕或者手动exit/die。若该对象的所有引用被删除则不会触发上述情况。
<?php
//在使用Thinkphp3.23框架开发时发现下面3个Action(实现功能其实都一样):只有aAction会触发上述情况(使用了exit die等)。
//原因:TP会删除对该对象的引用(非手动 调用控制器的变量为App::exec()内局部变量,会在执行完之后自动销毁)。 function aAction(){ if(true){ //doSomeThing; exit; } //doElseSomeThing; }
function bAction(){
if(true){
//doSomeThing;
return ;
}
//doElseSomeThing;
}
function cAction(){
if(true){
//doSomeThing;
}else{
//doElseSomeThing;
}
}
欢迎各位指点!