discuz采用‘编译型’模版机制,其核心思想是将页面布局以普通网页文件存贮,在这些文件中插入需要动态显示数据的“仿PHP代码”,模版系统再把模版源文件中的“仿PHP代码”通过DZ的模版的引擎转换为真正的PHP代码并将其另存为PHP程序格式的“模版缓存文件”,这个转换过程常常被称为“编译”。
在用户浏览的时候,模版系统载入“模版缓存文件”,将PHP程序运行的结果带入这些文件后执行输出,当模版源文件丢失或其内容被修改后,模版系统会自动检测并重建“模版缓存文件”。
template()函数的作用是将参数$tFile表示的模版;源文件‘编译’为目标‘模版缓存文件’,参数$templateid表示模版系统编号,用以区分相同名称不同套系的模版缓存文件。模版“编译”的原理是使用文件读取函数读入模版文件,然后使用正则表达式模版文件中的‘仿PHP代码’替换成真正的PHP代码,写入到指定目录下的目标‘模版缓存文件’。
在Disvuz中当仿PHP代码中if分支和loop循环结构最多为6层。
Section One–./include/global.func.php—->template function

function template($file, $templateid = 0, $tpldir = '') { global $tplrefresh;   $tpldir = $tpldir ? $tpldir : TPLDIR; $templateid = $templateid ? $templateid : TEMPLATEID; $tplfile = DISCUZ_ROOT.'./'.$tpldir.'/'.$file.'.htm'; $objfile = DISCUZ_ROOT.'./forumdata/templates/'.$templateid.'_'.$file.'.tpl.php'; if(TEMPLATEID != 1 && $templateid != 1 && !file_exists($tplfile)) {   return template($file, 1, './templates/default/');    }  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;
}
这个函数一共有三个传入参数: $file 表示模板名$templateid 表示模板id$tpldir 表示模板目录global $tplrefresh;这个是把$tplrefresh作为一个全局变量,tplrefresh表示是不是刷新模板 $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中,否则的话还是直接返回一个已经编译好的模板文件。

我们来了解一下PHP的工作,
PHP是一种可以混合php代码和HTML代码的语言
比如在一个PHP文件里,可以直接写入HTML代码,然后在需要写php代码的地方加上<?php ?>,在里面写代码就可以了,这种模板和代码混合的写法称为原生态写法,现在流行的wordpress就是这种写法,很多高手崇尚这种写法。比如这个代码就是原生态的写法完成的:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>><head><title><?php bloginfo('name'); ?> &rsaquo; <?php echo $title; ?></title><meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" /><?phpwp_admin_css( 'login', true );wp_admin_css( 'colors-fresh', true );if ( $is_iphone ) { ?>

但是我个人看了这种代码是会头疼的。。。因为太乱了。。。又不美观。。。而且如果很多人来写这个工程,就乱套了。能不能把模板和代码分开呢?这样美工就能专注模板了。。。
所以DISCUZ也这么干了。
我们把所有的PHP代码单独写在一起,放在某个页面的上面,里面都是一些赋值了的变量,比如这个帖子的内容。
下面再载入模板,就像我们上面看到的分析一样,那个第三步就相当于把那个模板页面所有内容放到这个forumdisplay页面的最下面
当然,这个包含进来的模板是经过编译的,也就是把那个特有我们写的模板转变成PHP和HTML混合的代码。
所以最后我们得到的这个PHP页面里究竟变成了什么了呢?
有童鞋说出来了,这样得到的不就是一个混合了HTML和PHP代码的原生态写法的php文件吗?对的。。。模板编译的结果就是最后给服务器运行一个原生态写法的php文件。
由于discuz模板编译的过程,是把templates文件下里对应的模板文件转变成原生态的写法,然后存放在cache的文件夹里,然后再包含进根目录下的文件里,所以大家也可以在缓存文件夹里的模板文件夹里查看到某个页面经过编译的原生态的php代码。

上面说了,经过模板编译的过程,把templates里面的htm文件变成原生态写法的php文件,那么我们可以肯定,上面的template函数肯定经过了一些特殊处理,把一定格式的htm文件转变成php文件,而这个htm文件一定要遵循某些符合这个函数转变规律的写法才行,否则就会编译错误。
而这个写法也就是我们这堂课的重点了。

这个函数的作用是检测已经存在模板缓存文件是否过期或者被强制更新,如果需要重新编译,则导入专门处理模板的文件/include/template.func.php,然后使用parse_template函数,对这个模板进行处理。
我们来看看parse_template函数,其实看名字也知道,这个才是真正的重中之重,分析这个里面的规律就可以知道其编译的规律了。

    function tplParse($tFile,$cFile){$fileContent=file_get_contents($tFile);$fileContent=preg_replace_callback("/^(\xef\xbb\xbf)/", function($r){}, $fileContent);$fileContent=preg_replace_callback("/\<\!\-\-\s*\\\$\{(.+?)\}\s*\-\-\>/is",function($r){return str_replace('\"', '"', '<?php echo ' . $r[1] . '; ?>');},$fileContent);$fileContent=preg_replace_callback("/\{(\\\$[a-zA-Z0-9_\[\]\\\ \-\'\,\%\*\/\.\(\)\>\'\"\$\x7f-\xff]+)\}/s",function($r){return str_replace('\"', '"', '<?php echo ' . $r[1] . '; ?>');},$fileContent);$fileContent = preg_replace_callback("#<!--\s*{\s*include\s+([^\{\}]+)\s*\}\s*-->#i", function($r){return '<?php include template("'.$r[1].'");?>';},$fileContent);.........file_put_contents($cFile,$fileContent);return true;}

这个里面是不是很多正则式匹配的过程啊,还有很多的preg_replace,当然。。。这里就是把htm里面的所有代码进行一次一次按规律把HTML和专用语法代码转变成标准的HTML+PHP代码的过程了。
替换次数很多,所以上面的代码省略了。
比如我们在模板里写入这句:

<h2>{$array[a]}</h2>

经过处理,就会变成这样的原生态写法:

<h2><?php echo $array['a']; ?></h2>

上面的在php服务器上不能运行,而下面的经过编译了,就可以直接运行了。
在PHP模板里我们还能写入PHP语句的,当然这个也要经过编译才能变成直接运行的php代码,比如if,else等,还有循环loop,用来变成foreach。这些在模板里作用很多,比如一个tab页面,大多是通过地址传值,然后经过IF等处理后,展示出来。这些固定的写法是必须背诵的,下面我会详细介绍,其实也是这个文里面最重要的部分了。

看了上面的部分,同学们已经了解了整个模板在DISCUZ中的处理过程了。那么我们来制作模板,知道这个原理后,最重要的可能就是要了解他们的语法了。
然后才好自己随心所欲的编写模板。
我总结了一下,下面会分条列出:
1,首先要说的是变量,我们从上面的分析可以知道,在根目录文件里,首先已经把变量都赋值好了。在模板里直接应用就可以了,而这个变量在DISCUZ模板里要这样写:

{$a},{$a[b]},{AAA}

这里分别代表了变量,数组中某个值,常量的写法。他们相当于:<?php echo $a ?>等语法。
2,模板语法。在模板里也能运用语法,这样可以判断然后展示出想要的模板样式。
首先说一下他们的通用写法,都要写在这个里面:

<!--{}-->

大家看这个是不是很熟悉啊,当然,细心的同学,我们在上一节课里已经说了注释的标示是<!---->
在这里多了一个{}然后里面就能写判断等语句了,写法如下:

<!--{if}--><!--{/if}-->
<!--{if}--><!--{else}--><!--{/if}-->
<!--{if}--><!--{elseif }--><!--{else}--><!--{if}-->

比如:

<!--{if $userid}-->欢迎您<!--{else}-->请登陆<!--{/if}-->

这就是一个简单的模板判断语句,判断用户时候有登陆
3,循环语句。这个东西太重要了。大家务必掌握。

<!--{loop $array $key $value)}--> <!--{/loop}-->

这个句法相当于

foreach($array as $key=>$value) {
}

作用就是把数组遍历输出。
里面的$array就是数据,可以是一维数组或者多维,多维的情况下可以使用$key[][]等方式展示出来。
这里的$key不一定要写出来,不写出来的时候,相当于直接遍历值而不用考虑键名。
比如首页的用户列表,帖子列表神马的都是把信息放入数组,然后在模板里遍历输出。

同学们看到这里可能有疑问,为啥米他们要用foreach而不用for或者while呢?这个问题你们怎么不去问DZ开发人员?
不过如果让我来写,我也会用foreach的 ,原因不明。。。
4,{lang }
载入语言包,他们很复杂的把所有的中文写到了语言包里去了。这样有一定的好处,不过吾觉得实在是太麻烦了。

5,{template }
载入另外一个模板。

6,{eval }
这个后面可以直接运行php代码,比如{eval echo ‘hello!’;},这个用多了会显得不专业,所以不要轻易用!

7,{LF}
换行符,大家从上面的代码也可以看出来

$template = str_replace("{LF}", "<?="\n"?>", $template);

8,{subtemplate }
这个也是载入,不过不会对载入的进行处理,可以理解为直接引用。一般在做边栏模块的时候用的多。
9,{csstemplate }
专门载入CSS文件的,因为在CSS文件中,我们会发现那个CSS也是htm结尾的,而且里面到底是使用哪个文件夹里的背景图片等等也是需要经过编译的。

10,{echo }
这个不用介绍了吧。不过这个你也能使用到的话,只能说明你要么是白痴要么是天才。

discuz模板机制相关推荐

  1. discuz模板机制应用

    discuz用多了,觉得它的模板确实好用,便将它的数据库操作.模板提取出来,小组了一下,用于单独的开发用. 经过一个商城网站的开发,应用已经非常顺手了.商城主站完成后,进行代理网站的开发,其实主要就是 ...

  2. Discuz!NT 模板机制分析(转)

    作为产品中的一大特色,模板机制一经推出,就引来了大家特别是站长们的关注.但它所饱受的风风 雨雨也成了那时不少人关注的话题.而今天本人将结合在产品组中的开发经历,介绍一下模板机制在设计 使用时的一些体会 ...

  3. 快速理解shopex模板机制经验教程(一)

    shopex是程序和模板分离的,这样就大大方便了大家可以做出自己漂亮的外观网站, 虽然很多地方分离得不够,比如一些核心的业务流程区基本大家就很难修改了,但是大部分还是满足网站基本要求的. 首先,说说模 ...

  4. C++函数模板机制结论

    函数模板机制结论: 编译器并不是把函数模板处理成能够处理任何类型的函数 函数模板通过具体类型产生不同的函数 编译器会对函数模板进行两次编译,在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后 ...

  5. c++模板--2(模板机制,模板的局限性,类模板,类模板做函数的参数)

    函数模板机制结论 编译器并不是把函数模板处理成能狗处理任何类型的函数 函数模板通过具体类型产生不同的函数 编译器会对函数模板进行两次编译,在声明的地方对模板代码的本身进行编译,在调用的地方对参数替换后 ...

  6. B75经典门户商业版discuz模板

    简介: B75经典门户商业版discuz模板,支持discuzx3.0版本,discuzx3.1版本,discuzx3.2版本,包括[门户首页].[门户文章列表].[门户文章详情].[论坛首页].[论 ...

  7. [系列教程] Discuz模板的制作方法

    Discuz模板的制作相对还是比较简单,现在应用中心的上线又涌现出来一大批模板开发作者,不管大家做免费模板还是商业模板,都希望每个开发者可以维护好自己的模板,给站长们一个好模板.Discuz模板的创建 ...

  8. magento邮件使用php,用Magento的Email模板机制发邮件

    Magento的Mage::getModel('core/email_template')模型可用来发信. 步骤I. 在你的模块(其实任意Module都可以)的etc/config.xml的根标签下添 ...

  9. Shopex模板机制总览(摘要版)

    Shopex模板机制总览(摘要版) 此文档旨在为 shopex 二次开发提供一个便利的参考信息,借以打开 shopex 架构的大门,希望能带给读者一种登堂入室的感觉.由于 shopex 是半开放源代码 ...

  10. Discuz模板多色设计 ZCOOL站酷素材源码

    Discuz模板多色设计 ZCOOL站酷素材源码 https://www.piaodoo.com/9387.html 菜鸟教程https://www.piaodoo.com 1.本模板为门户+论坛+个 ...

最新文章

  1. 前端(HTML/CSS/JS)-CSS编码规范
  2. python自动化办公培训_python-自动化办公
  3. swiper轮播器的常用案例分析(swiper hover停止mouseover停止)
  4. 关于fetch api这点事
  5. 【Yarn】Yarn 命令详解
  6. html5 成语连连看,全国通用五年级下册语文讲义-阅读与作文:学写读后感(含答案)[参考].pdf...
  7. python监控错误语句_Sentry错误日志监控使用方法解析
  8. Ubuntu下完全删除Edraw软件
  9. 没有密码怎么撤销工作表保护
  10. 酷派android sdk,酷派彩客易SDK配置说明
  11. OpenEuler上构建LFS8.4
  12. PHP获取自然周日期(周一~周日)
  13. html3d粒子球,Canvas粒子系统:3D球体
  14. 会声会影2022旗舰终极版详细功能介绍
  15. Android(thirteen)
  16. 别人问我:为什么程序员都不善言辞?惭愧啊!
  17. java基础--while循环实现存钱问题案例
  18. 视频修复工具recover_mp4,视频录制一半掉电,如何查看已保存数据?
  19. 3422. 【NOIP2013模拟】水叮当的舞步
  20. python自动调整格式_pycharm使用技巧——自动调整代码格式汇总

热门文章

  1. 英特尔移动处理器全面解析
  2. 现场总线-Can基础知识
  3. c 语言编程字谜,字谜游戏(a)C语言
  4. less文件中导入另一个less文件
  5. Ubertooth one“蓝牙扫描嗅探”使用教程
  6. 记一个embed嵌入flash、mp4播放视频
  7. OrCAD DSN文件无故消失解决办法
  8. 跟二项分布相关的统计检验方法
  9. 你需要一个什么样的网站开发流程?
  10. 车辆、行人跟踪一网打尽,超轻量、多类别、小目标跟踪系统开源了!