请选择 进入手机版 | 继续访问电脑版
查看: 62|回复: 0

Discuz模板加载机制详解

[复制链接]

494

主题

496

帖子

2576

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2576
发表于 2021-6-3 18:01:01 | 显示全部楼层 |阅读模式
通用模板机制
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),调用模板文件,
  1. checktplrefresh($tplfile, $tplfile, @filemtime(DISCUZ_ROOT.$cachefile), $templateid, $cachefile, $tpldir, $file);
复制代码
filemtime(DISCUZ_ROOT.$cashefile)获取缓存文件(文件路径根据模板文件生成)的更改时间,
  1. function checktplrefresh($maintpl, $subtpl, $timecompare, $templateid, $cachefile, $tpldir, $file) {
  2.         static $tplrefresh, $timestamp, $targettplname;
  3.         if($tplrefresh === null) {
  4.                 $tplrefresh = getglobal('config/output/tplrefresh');
  5.                 $timestamp = getglobal('timestamp');
  6.         }
  7.      //如果$timecompare为空(编译文件不存在),或者模板文件的更新时间(
  8.      @filemtime
  9.      (
  10.      DISCUZ_ROOT
  11.      .
  12.      $subtpl
  13.      ))大于$timecompar
  14.      //都会执行模板缓存重新编译
  15.      parse_template
  16.      (
  17.      $maintpl
  18.      ,
  19.       $templateid
  20.      ,
  21.       $tpldir
  22.      ,
  23.       $file
  24.      ,
  25.       $cachefile
  26.      )
  27.         if(empty($timecompare) || $tplrefresh == 1 || ($tplrefresh > 1 && !($timestamp % $tplrefresh))) {
  28.                 if(empty($timecompare) || @filemtime(DISCUZ_ROOT.$subtpl) > $timecompare) {
  29.                         require_once DISCUZ_ROOT.'/source/class/class_template.php';
  30.                         $template = new template();
  31.                         $template->parse_template($maintpl, $templateid, $tpldir, $file, $cachefile);
  32.                         if($targettplname === null) {
  33.                                 $targettplname = getglobal('style/tplfile');
  34.                                 if(!empty($targettplname)) {
  35.                                         include_once libfile('function/block');
  36.                                         $targettplname = strtr($targettplname, ':', '_');
  37.                                         update_template_block($targettplname, getglobal('style/tpldirectory'), $template->blocks);
  38.                                 }
  39.                                 $targettplname = true;
  40.                         }
  41.                         return TRUE;
  42.                 }
  43.         }
  44.         return FALSE;  
  45. }
复制代码
下面解析parse_template();
  1. function parse_template($tplfile, $templateid, $tpldir, $file, $cachefile) {
  2.                 $basefile = basename(DISCUZ_ROOT.$tplfile, '.htm');
  3.                 $file == 'common/header' && defined('CURMODULE') && CURMODULE && $file = 'common/header_'.CURMODULE;
  4.                 $this->file = $file;
  5.                 if($fp = @fopen(DISCUZ_ROOT.$tplfile, 'r')) {
  6.                         $template = @fread($fp, filesize(DISCUZ_ROOT.$tplfile));
  7.                         fclose($fp);
  8.                 } elseif($fp = @fopen($filename = substr(DISCUZ_ROOT.$tplfile, 0, -4).'.php', 'r')) {
  9.                         $template = $this->getphptemplate(@fread($fp, filesize($filename)));
  10.                         fclose($fp);
  11.                 } else {
  12.                         $tpl = $tpldir.'/'.$file.'.htm';
  13.                         $tplfile = $tplfile != $tpl ? $tpl.', '.$tplfile : $tplfile;
  14.                         $this->error('template_notfound', $tplfile);
  15.                 }
  16.                 $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]+\])*)";
  17.                 $const_regexp = "([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)";
  18.                 $headerexists = preg_match("/{(sub)?template\s+[\w\/]+?header\}/", $template);
  19.                 $this->subtemplates = array();
  20.                 for($i = 1; $i <= 3; $i++) {
  21.                         if(strexists($template, '{subtemplate')) {
  22.                                 $template = preg_replace("/[\n\r\t]*(\<\!\-\-)?\{subtemplate\s+([a-z0-9_:\/]+)\}(\-\-\>)?[\n\r\t]*/ies", "\$this->loadsubtemplate('\\2')", $template);
  23.                         }
  24.                 }
  25.                 $template = preg_replace("/([\n\r]+)\t+/s", "\\1", $template);
  26.                 $template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template);
  27.                 $template = preg_replace("/\{lang\s+(.+?)\}/ies", "\$this->languagevar('\\1')", $template);
  28.                 $template = preg_replace("/[\n\r\t]*\{block\/(\d+?)\}[\n\r\t]*/ie", "\$this->blocktags('\\1')", $template);
  29.                 $template = preg_replace("/[\n\r\t]*\{blockdata\/(\d+?)\}[\n\r\t]*/ie", "\$this->blockdatatags('\\1')", $template);
  30.                 $template = preg_replace("/[\n\r\t]*\{ad\/(.+?)\}[\n\r\t]*/ie", "\$this->adtags('\\1')", $template);
  31.                 $template = preg_replace("/[\n\r\t]*\{ad\s+([a-zA-Z0-9_\[\]]+)\/(.+?)\}[\n\r\t]*/ie", "\$this->adtags('\\2', '\\1')", $template);
  32.                 $template = preg_replace("/[\n\r\t]*\{date\((.+?)\)\}[\n\r\t]*/ie", "\$this->datetags('\\1')", $template);
  33.                 $template = preg_replace("/[\n\r\t]*\{avatar\((.+?)\)\}[\n\r\t]*/ie", "\$this->avatartags('\\1')", $template);
  34.                 $template = preg_replace("/[\n\r\t]*\{eval\s+(.+?)\s*\}[\n\r\t]*/ies", "\$this->evaltags('\\1')", $template);
  35.                 $template = preg_replace("/[\n\r\t]*\{csstemplate\}[\n\r\t]*/ies", "\$this->loadcsstemplate('\\1')", $template);
  36.                 $template = str_replace("{LF}", "<?="\\n"?>", $template);
  37.                 $template = preg_replace("/\{(\\\$[a-zA-Z0-9_\-\>\[\]\'"\$\.\x7f-\xff]+)\}/s", "<?=\\1?>", $template);
  38.                 $template = preg_replace("/\{hook\/(\w+?)(\s+(.+?))?\}/ie", "\$this->hooktags('\\1', '\\3')", $template);
  39.                 $template = preg_replace("/$var_regexp/es", "template::addquote('<?=\\1?>')", $template);
  40.                 $template = preg_replace("/\<\?\=\<\?\=$var_regexp\?\>\?\>/es", "\$this->addquote('<?=\\1?>')", $template);
  41.                 $headeradd = $headerexists ? "hookscriptoutput('$basefile');" : '';
  42.                 if(!empty($this->subtemplates)) {
  43.                         $headeradd .= "\n0\n";
  44.                         foreach($this->subtemplates as $fname) {
  45.                                 $headeradd .= "|| checktplrefresh('$tplfile', '$fname', ".time().", '$templateid', '$cachefile', '$tpldir', '$file')\n";
  46.                         }
  47.                         $headeradd .= ';';
  48.                 }
  49.                 if(!empty($this->blocks)) {
  50.                         $headeradd .= "\n";
  51.                         $headeradd .= "block_get('".implode(',', $this->blocks)."');";
  52.                 }
  53.                 $template = "<? if(!defined('IN_DISCUZ')) exit('Access Denied'); {$headeradd}?>\n$template";
  54.                 $template = preg_replace("/[\n\r\t]*\{template\s+([a-z0-9_:\/]+)\}[\n\r\t]*/ies", "\$this->stripvtags('<? include template(\'\\1\'); ?>')", $template);
  55.                 $template = preg_replace("/[\n\r\t]*\{template\s+(.+?)\}[\n\r\t]*/ies", "\$this->stripvtags('<? include template(\'\\1\'); ?>')", $template);
  56.                 $template = preg_replace("/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/ies", "\$this->stripvtags('<? echo \\1; ?>')", $template);
  57.                 $template = preg_replace("/([\n\r\t]*)\{if\s+(.+?)\}([\n\r\t]*)/ies", "\$this->stripvtags('\\1<? if(\\2) { ?>\\3')", $template);
  58.                 $template = preg_replace("/([\n\r\t]*)\{elseif\s+(.+?)\}([\n\r\t]*)/ies", "\$this->stripvtags('\\1<? } elseif(\\2) { ?>\\3')", $template);
  59.                 $template = preg_replace("/\{else\}/i", "<? } else { ?>", $template);
  60.                 $template = preg_replace("/\{\/if\}/i", "<? } ?>", $template);
  61.                 $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);
  62.                 $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);
  63.                 $template = preg_replace("/\{\/loop\}/i", "<? } ?>", $template);
  64.                 $template = preg_replace("/\{$const_regexp\}/s", "<?=\\1?>", $template);
  65.                 if(!empty($this->replacecode)) {
  66.                         $template = str_replace($this->replacecode['search'], $this->replacecode['replace'], $template);
  67.                 }
  68.                 $template = preg_replace("/ \?\>[\n\r]*\<\? /s", " ", $template);
  69.                 if(!@$fp = fopen(DISCUZ_ROOT.$cachefile, 'w')) {
  70.                         $this->error('directory_notfound', dirname(DISCUZ_ROOT.$cachefile));
  71.                 }
  72.                 $template = preg_replace("/"(http)?[\w\.\/:]+\?[^"]+?&[^"]+?"/e", "\$this->transamp('\\0')", $template);
  73.                 $template = preg_replace("/\<script[^\>]*?src="(.+?)"(.*?)\>\s*\<\/script\>/ies", "\$this->stripscriptamp('\\1', '\\2')", $template);
  74.                 $template = preg_replace("/[\n\r\t]*\{block\s+([a-zA-Z0-9_\[\]]+)\}(.+?)\{\/block\}/ies", "\$this->stripblock('\\1', '\\2')", $template);
  75.                 $template = preg_replace("/\<\?(\s{1})/is", "<?php\\1", $template);
  76.                 $template = preg_replace("/\<\?\=(.+?)\?\>/is", "<?php echo \\1;?>", $template);
  77.                 flock($fp, 2);
  78.                 fwrite($fp, $template);
  79.                 fclose($fp);
  80. }
复制代码

解析重点
解析的重点主要是
变量输出 :{$var}

条件判断
<!--{if $var}-->
     html
<!--{/if}-->

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

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

插件钩子:
<!--{hook/index_top}-->
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|蓄财网 ( 豫ICP备2021002293号 )

GMT+8, 2021-6-17 00:06 , Processed in 0.093544 second(s), 29 queries .

蓄财网 ©版权所有

© 2021 蓄财网(www.aixc.cn)

快速回复 返回顶部 返回列表