V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ly710
V2EX  ›  PHP

今天改了一天也没弄出来的一个 PHP bug 我要哭了 大家帮忙看看

  •  
  •   ly710 · 2015-03-23 19:22:53 +08:00 · 4338 次点击
    这是一个创建于 3535 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在项目用的貌似是改过的smarty模板,然后今天一个模板文件在服务器上死活编译不出来,但是在我本地是好的。下面是模板引擎:

    <?php
    
    function template($file, $templateid = 0) {
        $templateid = $templateid ? $templateid : TEMPLATEID;
        $tplfile = TPLDIR.$file.'.html';
        $objfile = TPLDIR_C.$templateid.'_'.$file.'.tpl.php';
        checktplrefresh($tplfile, $tplfile, @filemtime($objfile), $templateid);
        return $objfile;
    }
    
    function checktplrefresh($maintpl, $subtpl, $timecompare, $templateid,$tpldir=null) {
        if(empty($timecompare) || TPLREFRESH == 1 || (TPLREFRESH > 1 && !($GLOBALS['timestamp'] % TPLREFRESH))) {
            if(empty($timecompare) || @filemtime($subtpl) > $timecompare) {
                parse_template($maintpl, $templateid);
                return TRUE;
            }
        }
        return  FALSE;
    }
    
    function parse_template($tplfile, $templateid) {
        global $language;
        $nest = 6;
        $file = basename($tplfile, '.html');
        $objfile = TPLDIR_C.$templateid."_".$file.".tpl.php";
    
        if(!@$fp = fopen($tplfile, 'r')) {
            die("Current template file './".TPLDIR."/$file.html' not found or have no access.");
        }
    
        $template = @fread($fp, filesize($tplfile));
        fclose($fp);
    
        $var_regexp = "((\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)(\[[a-zA-Z0-9_\-\.\"\'\[\]\$\x7f-\xff]+\])*)";
        $const_regexp = "([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)";
    
        $template = preg_replace("/([\n\r]+)\t+/s", "\\1", $template);
        $template = preg_replace("/\<\!\-\-\{{(.+?)\}}\-\-\>/s", "{{\\1}}", $template);
        $template = preg_replace("/\{{lang\s+(.+?)\}}/ies", "languagevar('\\1')", $template);
        $template = str_replace("{{LF}}", "<?=\"\\n\"?>", $template);
    
        $template = preg_replace("/\{{(\\\$[a-zA-Z0-9_\[\]\'\"\$\.\x7f-\xff]+)\}}/s", "<?=\\1?>", $template);
    
        $template = preg_replace("/[\n\r\t]*\{{template\s+([a-z0-9_]+)\}}[\n\r\t]*/is", "\n<? include template('\\1'); ?>\n", $template);
        $template = preg_replace("/[\n\r\t]*\{{template\s+(.+?)\}}[\n\r\t]*/is", "\n<? include template('\\1'); ?>\n", $template);
        $template = preg_replace("/[\n\r\t]*\{{eval\s+(.+?)\}}[\n\r\t]*/ies", "stripvtags('<? \\1 ?>','')", $template);
        $template = preg_replace("/[\n\r\t]*\{{echo\s+(.+?)\}}[\n\r\t]*/ies", "stripvtags('<? echo \\1; ?>','')", $template);
        $template = preg_replace("/([\n\r\t]*)\{{elseif\s+(.+?)\}}([\n\r\t]*)/ies", "stripvtags('\\1<? } elseif(\\2) { ?>\\3','')", $template);
        $template = preg_replace("/([\n\r\t]*)\{{else\}}([\n\r\t]*)/is", "\\1<? } else { ?>\\2", $template);
    
        for($i = 0; $i < $nest; $i++) {
            $template = preg_replace("/[\n\r\t]*\{{loop\s+(\S+)\s+(\S+)\}}[\n\r]*(.+?)[\n\r]*\{{\/loop\}}[\n\r\t]*/ies", "stripvtags('<? if(is_array(\\1)) { foreach(\\1 as \\2) { ?>','\\3<? } } ?>')", $template);
            $template = preg_replace("/[\n\r\t]*\{{loop\s+(\S+)\s+(\S+)\s+(\S+)\}}[\n\r\t]*(.+?)[\n\r\t]*\{{\/loop\}}[\n\r\t]*/ies", "stripvtags('<? if(is_array(\\1)) { foreach(\\1 as \\2 => \\3) { ?>','\\4<? } } ?>')", $template);
            $template = preg_replace("/([\n\r\t]*)\{{if\s+(.+?)\}}([\n\r]*)(.+?)([\n\r]*)\{{\/if\}}([\n\r\t]*)/ies", "stripvtags('\\1<? if(\\2) { ?>\\3','\\4\\5<? } ?>\\6')", $template);
    
            //$template_back = preg_replace_callback ("/([\n\r\t]*)\{{if\s+(.+?)\}}([\n\r]*)(.+?)([\n\r]*)\{{\/if\}}([\n\r\t]*)/is", "match_call_back", $template); 
        }
    
        $template = preg_replace("/ \?\>[\n\r]*\<\? /s", " ", $template);
    
        if(!@$fp = fopen($objfile, 'w')) {
            die("Directory:".$objfile." not found or have no access.");
        }
    
        $template = preg_replace("/\"(http)?[\w\.\/:]+\?[^\"]+?&[^\"]+?\"/e", "transamp('\\0')", $template);
        $template = preg_replace("/\<script[^\>]*?src=\"(.+?)\"(.*?)\>\s*\<\/script\>/ise", "stripscriptamp('\\1', '\\2')", $template);
    
        flock($fp, 2);
        fwrite($fp, $template);
        fclose($fp);
    }
    
    $language = array
    (
        //'add_to_cart' => 'Add to cart',
        'login_input_missing' => 'Missing login input.',
    );
    
    function languagevar($var) {
        global $language;
        if(isset($language[$var])) {
            return $language[$var];
        } else {
            return $var;
        }
    }
    
    
    function transamp($str) {
        $str = str_replace('&', '&amp;', $str);
        $str = str_replace('&amp;amp;', '&amp;', $str);
        $str = str_replace('\"', '"', $str);
        return $str;
    }
    
    function stripvtags($expr, $statement) {
        $expr = str_replace("\\\"", "\"", preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\\1", $expr));
        $statement = str_replace("\\\"", "\"", $statement);
        return $expr.$statement;
    }
    
    function stripscriptamp($s, $extra) {
        $extra = str_replace('\\"', '"', $extra);
        $s = str_replace('&amp;', '&', $s);
        return "<script src=\"$s\" type=\"text/javascript\"$extra></script>";
    }
    
    function match_call_back($matches) {
        return stripvtags($matches[1] . '<? if(' . $matches[2] . ') { ?>' .   $matches[3], $matches[4] . $matches[5] . '<? } ?>' . $matches[6]);
    }
    ?>
    

    查过之后 问题出在parse_template函数 for循环的这一句

    $template = preg_replace("/([\n\r\t]*)\{{if\s+(.+?)\}}([\n\r]*)(.+?)([\n\r]*)\{{\/if\}}([\n\r\t]*)/ies", "stripvtags('\\1<? if(\\2) { ?>\\3','\\4\\5<? } ?>\\6')", $template);
    

    在第三次循环执行完之后preg_replace函数报错,$template的值直接变成NULL。后来我把这句用网上推荐的preg_replace_callback改写了之后还是不行。

    $template_back = preg_replace_callback ("/([\n\r\t]*)\{{if\s+(.+?)\}}([\n\r]*)(.+?)([\n\r]*)\{{\/if\}}([\n\r\t]*)/is", "match_call_back", $template); 
    
    function match_call_back($matches) {
        return stripvtags($matches[1] . '<? if(' . $matches[2] . ') { ?>' .   $matches[3], $matches[4] . $matches[5] . '<? } ?>' . $matches[6]);
    }
    

    但是这两种方式在我本地PHP5.5上执行都是好的,在服务器上5.2就是编译不出来。而且两个函数都只是返回NULL,也不报错,我也没办法定位模板文件哪里出了问题。

    问问大家问题出在哪里,或者有什么方法可以把错误定位到模板文件的具体位置?

    9 条回复    2015-03-24 10:33:05 +08:00
    overflow
        1
    overflow  
       2015-03-23 19:39:00 +08:00
    你连 testing data 都不提供 ……
    BrightLiao
        2
    BrightLiao  
       2015-03-23 19:41:48 +08:00
    感觉是某一个正则错了,你每一个正则都把template值打出来看看,看到哪一步为空的,仔细检查那个正则看看
    Actrace
        3
    Actrace  
       2015-03-23 21:03:13 +08:00
    5.5和5.2的差别还是挺大的。。。
    imnpc
        4
    imnpc  
       2015-03-23 21:14:44 +08:00
    您PHP5.5下测试的程序 去PHP5.2上怎么能不出问题? 起码PHP5.3啊
    Tink
        5
    Tink  
       2015-03-24 00:49:54 +08:00 via iPhone
    先升级服务器环境,。
    kevinroot
        6
    kevinroot  
       2015-03-24 00:58:45 +08:00
    被5.2的服务器搞哭过 +1
    kevinroot
        7
    kevinroot  
       2015-03-24 01:00:44 +08:00
    本地装个集成环境,支持切换php版本的那种慢慢调吧,服务器上还是各种不爽
    ykjsw
        9
    ykjsw  
       2015-03-24 10:33:05 +08:00
    这个不就是discuz的模板函数吗,再从discuz新版里扣一份吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2300 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 16:12 · PVG 00:12 · LAX 08:12 · JFK 11:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.