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

2015-03-23 19:22:53 +08:00
 ly710

现在项目用的貌似是改过的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,也不报错,我也没办法定位模板文件哪里出了问题。

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

4198 次点击
所在节点    PHP
9 条回复
overflow
2015-03-23 19:39:00 +08:00
你连 testing data 都不提供 ……
BrightLiao
2015-03-23 19:41:48 +08:00
感觉是某一个正则错了,你每一个正则都把template值打出来看看,看到哪一步为空的,仔细检查那个正则看看
Actrace
2015-03-23 21:03:13 +08:00
5.5和5.2的差别还是挺大的。。。
imnpc
2015-03-23 21:14:44 +08:00
您PHP5.5下测试的程序 去PHP5.2上怎么能不出问题? 起码PHP5.3啊
Tink
2015-03-24 00:49:54 +08:00
先升级服务器环境,。
kevinroot
2015-03-24 00:58:45 +08:00
被5.2的服务器搞哭过 +1
kevinroot
2015-03-24 01:00:44 +08:00
本地装个集成环境,支持切换php版本的那种慢慢调吧,服务器上还是各种不爽
Doubear
2015-03-24 08:59:40 +08:00
\{{if\s+(.+?)\}}

这玩意不该是
\{\{if\s+(.+?)\}\}
么?
ykjsw
2015-03-24 10:33:05 +08:00
这个不就是discuz的模板函数吗,再从discuz新版里扣一份吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/178867

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX