[转]Discuz 模板原理分析

刚开始学PHP的时候,对模板解析实在是觉得很奇怪,不知道这个原理怎么实现的,后来看书看多了也明白有一个著名的Smarty在那,曾经也用过一段,不过感觉不是很好,就开始分析Discuz的模板技术是怎么实现的了,然后我把这个模板解析的代码分离出来了,觉得很好用,用了一段时间, Discuz的模板解析是用正则表达式替换一些模板中的规定的语言标记,然后呢,写到forumdata/templates中,再用include引用到index, forumdisplay等等中,和smarty的原理基本上相同,只是功能没有smarty那么多,smarty内建了一个cache来着…连个User Guide都几百页…

  呵呵,不过现在基本上两个都没用过,正则表达式好是好用,不过正则的效率不是很高,以前看PHP技术文档的时候说能不用正则就尽量不要用,那东西烦着,现在做什么项目基本上用的是框架,MVC的模式,View中的代码一般不用模板解析出来,混杂php代码在里面,也觉得不错,OOP的开发效率比较高,很多地方重用代码是很开心的~!

  Discuz的模板解析要分析出来只要用到两个文件:./include/global.func.php和. /include/template.func.php,global只要一个函数就够了,template要全部的文件下面我就分开讲一下,会比较详细,大家耐心看:

Section One–./include/global.func.php—->template function

1  <p>function template($file, $templateid = 0, $tpldir = '') {</p>
2<p>        global $tplrefresh; </p><p>        $tpldir = $tpldir ? $tpldir : TPLDIR;</p><p>        $templateid = $templateid ? $templateid : TEMPLATEID;</p><p>        $tplfile = DISCUZ_ROOT.'./'.$tpldir.'/'.$file.'.htm';</p><p>        $objfile = DISCUZ_ROOT.'./forumdata/templates/'.$templateid.'_'.$file.'.tpl.php'; </p><p>        if(TEMPLATEID != 1 && $templateid != 1 && !file_exists($tplfile)) {  </p><p>                return template($file, 1, './templates/default/'); </p><p>        } </p><p>        if($tplrefresh == 1 || ($tplrefresh > 1 && substr($GLOBALS['timestamp'], -1) > $tplrefresh)) {</p>
3                if(@filemtime($tplfile) > @filemtime($objfile)) {
4<p>                        require_once DISCUZ_ROOT.'./include/template.func.php';</p>                        parse_template($file, $templateid, $tpldir);
5                }
6  <p>        } </p><p>        return $objfile;</p>

}

复制代码

这个函数一共有三个传入参数: 

$file 表示模板名

$templateid 表示模板id

$tpldir 表示模板目录

global $tplrefresh;这个是把$tplrefresh作为一个全局变量,tplrefresh表示是不是刷新模板 

CODE:

$tpldir = $tpldir ? $tpldir : TPLDIR;

        $templateid = $templateid ? $templateid : TEMPLATEID;给$tpldir和$templateid赋值,如果没有传进来就用常量TPLDIR和TEMPLATEID给它们值 

$tplfile = DISCUZ_ROOT.’./’.$tpldir.’/’.$file.’.htm’;

        $objfile = DISCUZ_ROOT.’./forumdata/templates/’.$templateid.’_’.$file.’.tpl.php’;这里是把$tplfile(表示的是模板文件)和$objfile(表示的是要编译成的文件)赋值 

if(TEMPLATEID != 1 && $templateid != 1 && !file_exists($tplfile)) {

                return template($file, 1, ‘./templates/default/’);

        } 

防止TEMPLATEID不等于1且$templateid不等于1,而且模板文件不存在导致空白问题。

这里也可以算一个迭代,也可以不算,就是把1作为第二个参数再调用函数本身。

if($tplrefresh == 1 || ($tplrefresh > 1 && substr($GLOBALS['timestamp'], -1) > $tplrefresh)) {

                if(@filemtime($tplfile) > @filemtime($objfile)) {

                        require_once DISCUZ_ROOT.’./include/template.func.php’;

                        parse_template($file, $templateid, $tpldir);

                }

        }

        return $objfile;

很巧妙的一段,Discuz的模板缓存就体现在这里,如果你没打开模板刷新的话(config.inc.php->$tplrefresh=0),这里就直接返回一个$objfile了,而这个文件是你第一次建论坛的时候就写入的,如果你不改模板的话,关了是能提高相当一部分效率的!反之,如果你打开了模板刷新的话就接着判断是不是模板文件的建立时间大于 forumdata/templates下的文件,是的话就引用./include/template.func.php写入模板文件到 forumdata/templates中,否则的话还是直接返回一个已经编译好的模板文件。

关于template.func.php文件中函数的分析在下面:

001<p>
002</p><ul>
003    <p>//防止非法引用<br>
004     
005    if(!defined('IN_DISCUZ')) {<br>
006     
007            exit('Access Denied');<br>
008     
009    }<br>
010     
011    function parse_template($file, $templateid, $tpldir) {<br>
012     
013            global $language;<br>
014     
015            $nest = 5;<br>
016     
017            $tplfile = DISCUZ_ROOT."./$tpldir/$file.htm";<br>
018     
019            $objfile = DISCUZ_ROOT."./forumdata/templates/{$templateid}_$file.tpl.php";<br>
020     
021            if(!@$fp = fopen($tplfile, 'r')) {<br>
022     
023                    dexit("Current template file './$tpldir/$file.htm' not found or have no access!");<br>
024     
025            } elseif(!include_once language('templates', $templateid, $tpldir)) {<br>
026     
027                    dexit("<br>Current template pack do not have a necessary language file 'templates.lang.php' or have syntax error!");<br>
028     
029            }<br>
030     
031            $template = fread($fp, filesize($tplfile));<br>
032     
033            fclose($fp);<br>
034     
035            $var_regexp = "((\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)(\[[a-zA-Z0-9_\-\.\"\'\[\]\$\x7f-\xff]+\])*)";<br>
036     
037            $const_regexp = "([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)";<br>
038     
039            $template = preg_replace("/([\n\r]+)\t+/s", "\\1", $template);<br>
040     
041            $template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template);<br>
042     
043            $template = preg_replace("/\{lang\s+(.+?)\}/ies", "languagevar('\\1')", $template);<br>
044     
045            $template = preg_replace("/\{faq\s+(.+?)\}/ies", "faqvar('\\1')", $template);<br>
046     
047            $template = str_replace("{LF}", "<?=\"\\n\"?>", $template);<br>
048     
049            $template = preg_replace("/\{(\\\$[a-zA-Z0-9_\[\]\'\"\$\.\x7f-\xff]+)\}/s", "<?=\\1?>", $template);<br>
050     
051            $template = preg_replace("/$var_regexp/es", "addquote('<?=\\1?>')", $template);<br>
052     
053            $template = preg_replace("/\<\?\=\<\?\=$var_regexp\?\>\?\>/es", "addquote('<?=\\1?>')", $template);<br>
054     
055            $template = "<? if(!defined('IN_DISCUZ')) exit('Access Denied'); ?>\n$template";<br>
056     
057            $template = preg_replace("/[\n\r\t]*\{template\s+([a-z0-9_]+)\}[\n\r\t]*/is", "\n<? include template('\\1'); ?>\n", $template);<br>
058     
059            $template = preg_replace("/[\n\r\t]*\{template\s+(.+?)\}[\n\r\t]*/is", "\n<? include template(\\1); ?>\n", $template);<br>
060     
061            $template = preg_replace("/[\n\r\t]*\{eval\s+(.+?)\}[\n\r\t]*/ies", "stripvtags('\n<? \\1 ?>\n','')", $template);<br>
062     
063            $template = preg_replace("/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/ies", "stripvtags('\n<? echo \\1; ?>\n','')", $template);<br>
064     
065            $template = preg_replace("/[\n\r\t]*\{elseif\s+(.+?)\}[\n\r\t]*/ies", "stripvtags('\n<? } elseif(\\1) { ?>\n','')", $template);<br>
066     
067            $template = preg_replace("/[\n\r\t]*\{else\}[\n\r\t]*/is", "\n<? } else { ?>\n", $template);<br>
068     
069            for($i = 0; $i < $nest; $i++) {<br>
070     
071                    $template = preg_replace("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\}[\n\r]*(.+?)[\n\r]*\{\/loop\}[\n\r\t]*/ies", "stripvtags('\n<? if(is_array(\\1)) { foreach(\\1 as \\2) { ?>','\n\\3\n<? } } ?>\n')", $template);<br>
072     
073                    $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('\n<? if(is_array(\\1)) { foreach(\\1 as \\2 => \\3) { ?>','\n\\4\n<? } } ?>\n')", $template);<br>
074     
075                    $template = preg_replace("/[\n\r\t]*\{if\s+(.+?)\}[\n\r]*(.+?)[\n\r]*\{\/if\}[\n\r\t]*/ies", "stripvtags('\n<? if(\\1) { ?>','\n\\2\n<? } ?>\n')", $template);<br>
076     
077            }<br>
078            $template = preg_replace("/\{$const_regexp\}/s", "<?=\\1?>", $template);<br>
079     
080            $template = preg_replace("/ \?\>[\n\r]*\<\? /s", " ", $template);<br>
081     
082    <br>
083     
084            if(!@$fp = fopen($objfile, 'w')) {<br>
085     
086                    dexit("Directory './forumdata/templates/' not found or have no access!");<br>
087     
088            }<br>
089     
090    <br>
091     
092            $template = preg_replace("/\"(http)?[\w\.\/:]+\?[^\"]+?&[^\"]+?\"/e", "transamp('\\0')", $template);<br>
093     
094            $template = preg_replace("/\<script[^\>]*?src=\"(.+?)\".*?\>\s*\<\/script\>/ise", "stripscriptamp('\\1')", $template);<br>
095     
096            flock($fp, 2);<br>
097     
098            fwrite($fp, $template);<br>
099     
100            fclose($fp);<br>
101     
102    } <br>
103     
104    function transamp($str) {<br>
105     
106            $str = str_replace('&', '&', $str);<br>
107     
108            $str = str_replace('&', '&', $str);<br>
109     
110            $str = str_replace('\"', '"', $str);<br>
111     
112            return $str;<br>
113     
114    } <br>
115     
116    function addquote($var) {<br>
117     
118            return str_replace("\\\"", "\"", preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));<br>
119     
120    }<br>
121     
122    function languagevar($var) {<br>
123     
124            if(isset($GLOBALS['language'][$var])) {<br>
125     
126                    return $GLOBALS['language'][$var];<br>
127     
128            } else {<br>
129     
130                    return "!$var!";<br>
131     
132            }<br>
133     
134    } <br>
135     
136    function faqvar($var) {<br>
137     
138            global $_DCACHE;<br>
139     
140            include_once DISCUZ_ROOT.'./forumdata/cache/cache_faqs.php';<br>
141     
142    <br>
143     
144            if(isset($_DCACHE['faqs'][$var])) {<br>
145     
146                    return '<a href="faq.php?action=message&id='.$_DCACHE['faqs'][$var]['id'].'" target="_blank">'.$_DCACHE['faqs'][$var]['keyword'].'</a>';<br>
147     
148            } else {<br>
149     
150                    return "!$var!";<br>
151     
152            }<br>
153     
154    } <br>
155    function stripvtags($expr, $statement) {<br>
156     
157            $expr = str_replace("\\\"", "\"", preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\\1", $expr));<br>
158     
159            $statement = str_replace("\\\"", "\"", $statement);<br>
160     
161            return $expr.$statement;<br>
162     
163    } </p><p>function stripscriptamp($s) {<br>
164     
165            $s = str_replace('&', '&', $s);<br>
166     
167            return "<script src=\"$s\" type=\"text/javascript\"></script>";<br>
168     
169    }
170</p>
171<p></p></ul>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值