好久没写博客了。
我们的一个项目用的thinkphp框架,当在debug模式下面运行很正常,但切换到生产模式时,刷新页面第一次可以正常显示,刷新第二次会出现错误如下:
Fatal error: Call to undefined function ThinkC() in /home/work/huangxuan/anti/Protected/ThinkPHP/Library/Think/Think.class.php on line 301
我们很自然的找到了出错所在的位置:
static public function halt($error) {
...
$error_page = C('ERROR_PAGE');
...
}
说明C函数没有定义,但这个函数是框架函数,怎么会没有定义 ?
继续看这个halt函数,发现它是框架的错误处理函数,也就是PHP遇到所有的问题后,最终会执行这个函数。
于是我们就在此函数的第一句话中打印var_dump($error);如下:
array(4) { | |
["type"]=> | |
int(4) | |
["message"]=> | |
string(48) "syntax error, unexpected 'function' (T_FUNCTION)" | |
["file"]=> | |
string(74) "/home/work/huangxuan/anti/Protected/Application/Runtime/common~runtime.php" | |
["line"]=> | |
int(1) | |
} |
继续找文件/home/work/huangxuan/anti/Protected/Application/Runtime/common~runtime.php,我们知道这个文件是thinkphp把框架核心程序文件去掉空格和注释后,揉到了一起,目的是提高效率。
但这个文件只有一行,我们也没法定位原因。
这也难不到我们,我们把这个文件一行分成多行,怎么分呢,批量替换,在每一个分号后面都加上换行符,再次刷新页面,我们就可以看到出错的行了:
array(4) { | |
["type"]=> | |
int(4) | |
["message"]=> | |
string(48) "syntax error, unexpected 'function' (T_FUNCTION)" | |
["file"]=> | |
string(74) "/home/work/huangxuan/anti/Protected/Application/Runtime/common~runtime.php" | |
["line"]=> | |
int(888) | |
} |
在第888行,我们发现
namespace {p function C($name=null, $value=null,$default=null) ...
类似这样的代码,大括号后面的那个p就是错误原因所在,但为什么程序中会多了一个字母p呢,我们继续找这段程序的原始位置,
/home/work/huangxuan/anti/Protected/ThinkPHP/Common/functions.php除去注释后的第一行:
function C($name=null, $value=null,$default=null) {....
为什么这个函数前面会有个p呢,我们几个人瞅了半天也没瞅出来,后来眼尖的同时发现php脚本第一行的标记(这里有个空格)<?php前面有个空格,去掉空格后果然好了。
但为什么一个空格会造成出现一个多余的字母p呢?
终于我总结出来,thinkphp在把程序揉到一起时,要把每个文件最前面的<?php标记去掉,它肯定是脑残的把前5个字符去掉,前面多了一个空格,自然就会多出来一个字母p....
大功告成!
但还没完,我得找到实实在在的证据,经过对框架的阅读,终于找到位置:
home/work/huangxuan/anti/Protected/ThinkPHP/Mode/Api/functions.php的compile函数的第二行:
$content = trim(substr($content, 5));
果真就是这么脑残的处理....
后记:这个错误我们两个人处理了半下午,各种找日志啥的,最终还是找到原因,其实过程不像博客中说的那么顺利