ThinkPHP3.1在PHP7下页面空白的解决方案

浏览:7565 发布日期:2016/06/28 分类:技术分享
先把BUG原因扔出来:模板解析出了问题。


之前一直用PHP5.6做开发,听说过PHP出7了,不过一直没尝试。直到前两天,处理(大于2038年 || 小于1900年)时间戳,发现mktime()返回False的问题,才意识到,估计不换是不行了。这明显是超出了取值范围,但2038年的问题按理说只存在于32位系统下,我系统是64位,那就只能是PHP的问题了。果断升级到7,问题解决。

但是,但是,但是!解决问题的同时往往会制造新的麻烦。此乃真理~ 所以,所有使用了模板的页面全都空白了。

初步怀疑是模板解析出了问题,追变量吧。display()、fetch()、tag()、B()这几个函数看下来,还是没能解决问题。因为B()里边是以这种形式进行调用的:$behavior->$method($params); 不太方便追踪,都打印出来又乱(我是个得了懒癌的强迫症),于是换一种简单的思路,读Log。

运行完页面,看Log如下(节选):NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Core\Db.class.php 第 605 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 273 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 168 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 404 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 404 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 404 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 404 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 399 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 404 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 404 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 404 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 404 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 197 行.
NOTIC: [2] preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead D:\PHP\WWW\ThinkPHP\Lib\Template\ThinkTemplate.class.php 第 137 行.
错误基本都在ThinkTemplate.class.php里,看文件名,这个是操作模板的。错误的原因是因为PHP7里删除了preg_replace()的/e参数,其实这个参数在PHP5里就已经废除了,只不过没有删除,所以还能用。官方给出的建议是,用preg_replace_callback()代替preg_replace() /e。

以ThinkTemplate.class.php 第 404 行左右的代码为例,修改如下:if(!$closeTag)
{
    /*
    $patterns = '/'.$begin.$parseTag.$n1.'\/(\s*?)'.$end.'/eis';
    $replacement = "\$this->parseXmlTag('$tagLib', '$tag', '$1', '')";
    $content = preg_replace($patterns, $replacement, $content);
    */
    
    // By Legolas 2016-06-28 00:59
    $patterns = '/'.$begin.$parseTag.$n1.'\/(\s*?)'.$end.'/is';
    $content = preg_replace_callback($patterns, function($match)use($tagLib, $tag){return $this->parseXmlTag($tagLib, $tag, $match[1], '');},$content);
}
else
{
    /*
    $patterns = '/'.$begin.$parseTag.$n1.$end.'(.*?)'.$begin.'\/'.$parseTag.'(\s*?)'.$end.'/eis';
    $replacement = "\$this->parseXmlTag('$tagLib', '$tag', '$1', '$2')";
    for($i=0; $i<$level; $i++)
    {
        $content = preg_replace($patterns, $replacement, $content);
    }
    */
    // By Legolas 2016-06-28 00:52
    $patterns = '/'.$begin.$parseTag.$n1.$end.'(.*?)'.$begin.'\/'.$parseTag.'(\s*?)'.$end.'/is';
    for($i=0; $i<$level; $i++)
    {
        $content = preg_replace_callback($patterns, function ($match)use($tagLib, $tag){return $this->parseXmlTag($tagLib, $tag, $match[1], $match[2]);}, $content);
    }
}
把Log中报错的位置都改掉,页面就可以正常显示了。

关于正则,再多说两句:
1、正则中,“/1”、“$1”表示第一个括号匹配的内容,“/2”、“$2”表示第二个括号匹配的内容,依此类推。
2、官方建议,preg_replace_callback()的回调使用匿名函数,参数$match为正则匹配的结果(数组),$match[1]表示第一个括号匹配的内容,依此类推。
3、若匿名函数需要使用外部变量,需要在定义函数时,使用use()传参。


我花了点时间,把代码里全部使用preg_replace() /e的地方,全都替换成了preg_replace_callback(),跟我一样得了懒癌不爱动手的朋友可以直接下载http://code.taobao.org/svn/share2016/trunk/ThinkPHP_Repaire.rar。如果发现BUG,欢迎指正。另外,这个框架因为是日常工作中用的,所以还集成了支付宝网页支付、极光推送、小米推送、PHPMail的第三方类库,都放在Extend\Vendor里,需要的可以直接拿来用~
最佳答案
评论( 相关
后面还有条评论,点击查看>>