discuz模板機制解析

通用模板機制

PHP通用的模板機制,流程一般是
1.初始化模板類
2.設置模板變量
3.分析模板中的的模板變量
4.輸出內容

discuz模板機制

解析流程

discuz中的模板機制,將這一流程全都寫在template()函數內的checktplrefresh(),編譯生成緩存文件(如果模板緩存文件不存在,或者緩存文件的更改時間小於模板文件的更改時間),
1.初始化模板類,$template = new template();
2.解析模板變量(編譯生成模板緩存文件),$template->parse_template($maintpl, $templateid, $tpldir, $file, $cachefile);
3.執行tempalte的php腳本中,直接 include template()返回的緩存文件,輸出編譯後內容。
下面是代碼解析
template($tpl),調用模板文件,
checktplrefresh($tplfile, $tplfile, @filemtime(DISCUZ_ROOT.$cachefile), $templateid, $cachefile, $tpldir, $file);

filemtime(DISCUZ_ROOT.$cashefile)獲取緩存文件(文件路徑根據模板文件生成)的更改時間,
function checktplrefresh($maintpl, $subtpl, $timecompare, $templateid, $cachefile, $tpldir, $file) {
static $tplrefresh, $timestamp, $targettplname;
if($tplrefresh === null) {
$tplrefresh = getglobal('config/output/tplrefresh');
$timestamp = getglobal('timestamp');
}
//如果$timecompare爲空(編譯文件不存在),或者模板文件的更新時間(@filemtime(DISCUZ_ROOT.$subtpl))大於$timecompar
//都會執行模板緩存重新編譯parse_template($maintpl, $templateid, $tpldir, $file, $cachefile)
 
if(empty($timecompare) || $tplrefresh == 1 || ($tplrefresh > 1 && !($timestamp % $tplrefresh))) {
if(empty($timecompare) || @filemtime(DISCUZ_ROOT.$subtpl) > $timecompare) {
require_once DISCUZ_ROOT.'/source/class/class_template.php';
$template = new template();
$template->parse_template($maintpl, $templateid, $tpldir, $file, $cachefile);
if($targettplname === null) {
$targettplname = getglobal('style/tplfile');
if(!empty($targettplname)) {
include_once libfile('function/block');
$targettplname = strtr($targettplname, ':', '_');
update_template_block($targettplname, getglobal('style/tpldirectory'), $template->blocks);
}
$targettplname = true;
}
return TRUE;
}
}
return FALSE;
}

下面解析parse_template();

function parse_template($tplfile, $templateid, $tpldir, $file, $cachefile) {
$basefile = basename(DISCUZ_ROOT.$tplfile, '.htm');
$file == 'common/header' && defined('CURMODULE') && CURMODULE && $file = 'common/header_'.CURMODULE;
$this->file = $file;
 
if($fp = @fopen(DISCUZ_ROOT.$tplfile, 'r')) {
$template = @fread($fp, filesize(DISCUZ_ROOT.$tplfile));
fclose($fp);
} elseif($fp = @fopen($filename = substr(DISCUZ_ROOT.$tplfile, 0, -4).'.php', 'r')) {
$template = $this->getphptemplate(@fread($fp, filesize($filename)));
fclose($fp);
} else {
$tpl = $tpldir.'/'.$file.'.htm';
$tplfile = $tplfile != $tpl ? $tpl.', '.$tplfile : $tplfile;
$this->error('template_notfound', $tplfile);
}
 
$var_regexp = "((\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\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]*)";
 
$headerexists = preg_match("/{(sub)?template\s+[\w\/]+?header\}/", $template);
$this->subtemplates = array();
for($i = 1; $i <= 3; $i++) {
if(strexists($template, '{subtemplate')) {
$template = preg_replace("/[\n\r\t]*(\<\!\-\-)?\{subtemplate\s+([a-z0-9_:\/]+)\}(\-\-\>)?[\n\r\t]*/ies", "\$this->loadsubtemplate('\\2')", $template);
}
}
 
$template = preg_replace("/([\n\r]+)\t+/s", "\\1", $template);
$template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template);
$template = preg_replace("/\{lang\s+(.+?)\}/ies", "\$this->languagevar('\\1')", $template);
$template = preg_replace("/[\n\r\t]*\{block\/(\d+?)\}[\n\r\t]*/ie", "\$this->blocktags('\\1')", $template);
$template = preg_replace("/[\n\r\t]*\{blockdata\/(\d+?)\}[\n\r\t]*/ie", "\$this->blockdatatags('\\1')", $template);
$template = preg_replace("/[\n\r\t]*\{ad\/(.+?)\}[\n\r\t]*/ie", "\$this->adtags('\\1')", $template);
$template = preg_replace("/[\n\r\t]*\{ad\s+([a-zA-Z0-9_\[\]]+)\/(.+?)\}[\n\r\t]*/ie", "\$this->adtags('\\2', '\\1')", $template);
$template = preg_replace("/[\n\r\t]*\{date\((.+?)\)\}[\n\r\t]*/ie", "\$this->datetags('\\1')", $template);
$template = preg_replace("/[\n\r\t]*\{avatar\((.+?)\)\}[\n\r\t]*/ie", "\$this->avatartags('\\1')", $template);
$template = preg_replace("/[\n\r\t]*\{eval\s+(.+?)\s*\}[\n\r\t]*/ies", "\$this->evaltags('\\1')", $template);
$template = preg_replace("/[\n\r\t]*\{csstemplate\}[\n\r\t]*/ies", "\$this->loadcsstemplate('\\1')", $template);
$template = str_replace("{LF}", "<?=\"\\n\"?>", $template);
$template = preg_replace("/\{(\\\$[a-zA-Z0-9_\-\>\[\]\'\"\$\.\x7f-\xff]+)\}/s", "<?=\\1?>", $template);
$template = preg_replace("/\{hook\/(\w+?)(\s+(.+?))?\}/ie", "\$this->hooktags('\\1', '\\3')", $template);
$template = preg_replace("/$var_regexp/es", "template::addquote('<?=\\1?>')", $template);
$template = preg_replace("/\<\?\=\<\?\=$var_regexp\?\>\?\>/es", "\$this->addquote('<?=\\1?>')", $template);
 
$headeradd = $headerexists ? "hookscriptoutput('$basefile');" : '';
if(!empty($this->subtemplates)) {
$headeradd .= "\n0\n";
foreach($this->subtemplates as $fname) {
$headeradd .= "|| checktplrefresh('$tplfile', '$fname', ".time().", '$templateid', '$cachefile', '$tpldir', '$file')\n";
}
$headeradd .= ';';
}
 
if(!empty($this->blocks)) {
$headeradd .= "\n";
$headeradd .= "block_get('".implode(',', $this->blocks)."');";
}
 
$template = "<? if(!defined('IN_DISCUZ')) exit('Access Denied'); {$headeradd}?>\n$template";
 
$template = preg_replace("/[\n\r\t]*\{template\s+([a-z0-9_:\/]+)\}[\n\r\t]*/ies", "\$this->stripvtags('<? include template(\'\\1\'); ?>')", $template);
$template = preg_replace("/[\n\r\t]*\{template\s+(.+?)\}[\n\r\t]*/ies", "\$this->stripvtags('<? include template(\'\\1\'); ?>')", $template);
$template = preg_replace("/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/ies", "\$this->stripvtags('<? echo \\1; ?>')", $template);
 
$template = preg_replace("/([\n\r\t]*)\{if\s+(.+?)\}([\n\r\t]*)/ies", "\$this->stripvtags('\\1<? if(\\2) { ?>\\3')", $template);
$template = preg_replace("/([\n\r\t]*)\{elseif\s+(.+?)\}([\n\r\t]*)/ies", "\$this->stripvtags('\\1<? } elseif(\\2) { ?>\\3')", $template);
$template = preg_replace("/\{else\}/i", "<? } else { ?>", $template);
$template = preg_replace("/\{\/if\}/i", "<? } ?>", $template);
 
$template = preg_replace("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\}[\n\r\t]*/ies", "\$this->stripvtags('<? if(is_array(\\1)) foreach(\\1 as \\2) { ?>')", $template);
$template = preg_replace("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}[\n\r\t]*/ies", "\$this->stripvtags('<? if(is_array(\\1)) foreach(\\1 as \\2 => \\3) { ?>')", $template);
$template = preg_replace("/\{\/loop\}/i", "<? } ?>", $template);
 
$template = preg_replace("/\{$const_regexp\}/s", "<?=\\1?>", $template);
if(!empty($this->replacecode)) {
$template = str_replace($this->replacecode['search'], $this->replacecode['replace'], $template);
}
$template = preg_replace("/ \?\>[\n\r]*\<\? /s", " ", $template);
 
if(!@$fp = fopen(DISCUZ_ROOT.$cachefile, 'w')) {
$this->error('directory_notfound', dirname(DISCUZ_ROOT.$cachefile));
}
 
$template = preg_replace("/\"(http)?[\w\.\/:]+\?[^\"]+?&[^\"]+?\"/e", "\$this->transamp('\\0')", $template);
$template = preg_replace("/\<script[^\>]*?src=\"(.+?)\"(.*?)\>\s*\<\/script\>/ies", "\$this->stripscriptamp('\\1', '\\2')", $template);
$template = preg_replace("/[\n\r\t]*\{block\s+([a-zA-Z0-9_\[\]]+)\}(.+?)\{\/block\}/ies", "\$this->stripblock('\\1', '\\2')", $template);
$template = preg_replace("/\<\?(\s{1})/is", "<?php\\1", $template);
$template = preg_replace("/\<\?\=(.+?)\?\>/is", "<?php echo \\1;?>", $template);
 
flock($fp, 2);
fwrite($fp, $template);
fclose($fp);
}

解析重點

解析的重點主要是
變量輸出 :{$var}

條件判斷
<!--{if $var}-->
     html
<!--{/if}-->

循環語句:
<!--{loop $arr $key $val}-->
    HTML語句
<!--{/loop}-->

嵌套模板內容:
<!--{template common/header}-->

插件鉤子:
<!--{hook/index_top}-->








發佈了31 篇原創文章 · 獲贊 1 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章