Heim >Backend-Entwicklung >PHP-Tutorial >Discuz的模板引擎

Discuz的模板引擎

WBOY
WBOYOriginal
2016-07-25 09:06:181387Durchsuche
填写您的邮件地址,订阅我们的精彩内容:

Discuz的模板引擎 一个比较好的模板引擎类,很久以前就在网上找到,目测这个Discuz的模板引擎应该很老了,是DZ7.2以前的版本了,自己也用得很顺手,分享下这个模板类。

有两个文件。一个模板类,一个模板替换中需要用到的函数
原文地址:http://blog.qita.in

  1. ?/**
  2. * 模板类 - 使用 Discuz 模板引擎解析
  3. * http://blog.qita.in
  4. */
  5. require_once (DIR_ROOT . '/../function/template.func.php');
  6. class Template {
  7. const DIR_SEP = DIRECTORY_SEPARATOR;
  8. /**
  9. * 模板实例
  10. *
  11. * @staticvar
  12. * @var object Template
  13. */
  14. protected static $_instance;
  15. /**
  16. * 模板参数信息
  17. *
  18. * @var array
  19. */
  20. protected $_options = array();
  21. /**
  22. * 单件模式调用方法
  23. *
  24. * @static
  25. * @return object Template
  26. */
  27. public static function getInstance() {
  28. if (!self :: $_instance instanceof self)
  29. self :: $_instance = new self();
  30. return self :: $_instance;
  31. }
  32. /**
  33. * 构造方法
  34. *
  35. * @return void
  36. */
  37. private function __construct() {
  38. $this -> _options = array('template_dir' => 'templates' . self :: DIR_SEP, // 模板文件所在目录
  39. 'cache_dir' => 'templates' . self :: DIR_SEP . 'cache' . self :: DIR_SEP, // 缓存文件存放目录
  40. 'auto_update' => false, // 当模板文件改动时是否重新生成缓存
  41. 'cache_lifetime' => 0, // 缓存生命周期(分钟),为 0 表示永久
  42. );
  43. }
  44. /**
  45. * 设定模板参数信息
  46. *
  47. * @param array $options 参数数组
  48. * @return void
  49. */
  50. public function setOptions(array $options) {
  51. foreach ($options as $name => $value)
  52. $this -> set($name, $value);
  53. }
  54. /**
  55. * 设定模板参数
  56. *
  57. * @param string $name 参数名称
  58. * @param mixed $value 参数值
  59. * @return void
  60. */
  61. public function set($name, $value) {
  62. switch ($name) {
  63. case 'template_dir':
  64. $value = $this -> _trimpath($value);
  65. if (!file_exists($value))
  66. $this -> _throwException("未找到指定的模板目录 \"$value\"");
  67. $this -> _options['template_dir'] = $value;
  68. break;
  69. case 'cache_dir':
  70. $value = $this -> _trimpath($value);
  71. if (!file_exists($value))
  72. $this -> _throwException("未找到指定的缓存目录 \"$value\"");
  73. $this -> _options['cache_dir'] = $value;
  74. break;
  75. case 'auto_update':
  76. $this -> _options['auto_update'] = (boolean) $value;
  77. break;
  78. case 'cache_lifetime':
  79. $this -> _options['cache_lifetime'] = (float) $value;
  80. break;
  81. default:
  82. $this -> _throwException("未知的模板配置选项 \"$name\"");
  83. }
  84. }
  85. /**
  86. * 通过魔术方法设定模板参数
  87. *
  88. * @see Template::set()
  89. * @param string $name 参数名称
  90. * @param mixed $value 参数值
  91. * @return void
  92. */
  93. public function __set($name, $value) {
  94. $this -> set($name, $value);
  95. }
  96. /**
  97. * 获取模板文件
  98. *
  99. * @param string $file 模板文件名称
  100. * @return string
  101. */
  102. public function getfile($file) {
  103. $cachefile = $this -> _getCacheFile($file);
  104. if (!file_exists($cachefile))
  105. $this -> cache($file);
  106. return $cachefile;
  107. }
  108. /**
  109. * 检测模板文件是否需要更新缓存
  110. *
  111. * @param string $file 模板文件名称
  112. * @param string $md5data 模板文件 md5 校验信息
  113. * @param integer $md5data 模板文件到期时间校验信息
  114. * @return void
  115. */
  116. public function check($file, $md5data, $expireTime) {
  117. if ($this -> _options['auto_update'] && md5_file($this -> _getTplFile($file)) != $md5data)
  118. $this -> cache($file);
  119. if ($this -> _options['cache_lifetime'] != 0 && (time() - $expireTime >= $this -> _options['cache_lifetime'] * 60))
  120. $this -> cache($file);
  121. }
  122. /**
  123. * 对模板文件进行缓存
  124. *
  125. * @param string $file 模板文件名称
  126. * @return void
  127. */
  128. public function cache($file) {
  129. $tplfile = $this -> _getTplFile($file);
  130. if (!is_readable($tplfile)) {
  131. $this -> _throwException("模板文件 \"$tplfile\" 未找到或者无法打开");
  132. }
  133. // 取得模板内容
  134. $template = file_get_contents($tplfile);
  135. // 过滤
  136. $template = preg_replace("/\/s", "{\\1}", $template);
  137. // 替换语言包变量
  138. // $template = preg_replace("/\{lang\s+(.+?)\}/ies", "languagevar('\\1')", $template);
  139. // 替换 PHP 换行符
  140. $template = str_replace("{LF}", "=\"\\n\"?>", $template);
  141. // 替换直接变量输出
  142. $varRegexp = "((\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)"
  143. . "(\[[a-zA-Z0-9_\-\.\"\'\[\]\$\x7f-\xff]+\])*)";
  144. $template = preg_replace("/\{(\\\$[a-zA-Z0-9_\[\]\'\"\$\.\x7f-\xff]+)\}/s", "=\\1?>", $template);
  145. $template = preg_replace("/$varRegexp/es", "addquote('=\\1?>')", $template);
  146. $template = preg_replace("/\\?\>/es", "addquote('=\\1?>')", $template);
  147. // 替换模板载入命令
  148. $template = preg_replace("/[\n\r\t]*\{template\s+([a-z0-9_]+)\}[\n\r\t]*/is",
  149. "\r\n include(\$template->getfile('\\1')); ?>\r\n",
  150. $template
  151. );
  152. $template = preg_replace("/[\n\r\t]*\{template\s+(.+?)\}[\n\r\t]*/is",
  153. "\r\n include(\$template->getfile(\\1)); ?>\r\n",
  154. $template
  155. );
  156. // 替换特定函数
  157. $template = preg_replace("/[\n\r\t]*\{eval\s+(.+?)\}[\n\r\t]*/ies",
  158. "stripvtags(' \\1 ?>','')",
  159. $template
  160. );
  161. $template = preg_replace("/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/ies",
  162. "stripvtags(' echo \\1; ?>','')",
  163. $template
  164. );
  165. $template = preg_replace("/([\n\r\t]*)\{elseif\s+(.+?)\}([\n\r\t]*)/ies",
  166. "stripvtags('\\1 } elseif(\\2) { ?>\\3','')",
  167. $template
  168. );
  169. $template = preg_replace("/([\n\r\t]*)\{else\}([\n\r\t]*)/is",
  170. "\\1 } else { ?>\\2",
  171. $template
  172. );
  173. // 替换循环函数及条件判断语句
  174. $nest = 5;
  175. for ($i = 0; $i $template = preg_replace("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\}[\n\r]*(.+?)[\n\r]*\{\/loop\}[\n\r\t]*/ies",
  176. "stripvtags(' if(is_array(\\1)) { foreach(\\1 as \\2) { ?>','\\3 } } ?>')",
  177. $template
  178. );
  179. $template = preg_replace("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}[\n\r\t]*(.+?)[\n\r\t]*\{\/loop\}[\n\r\t]*/ies",
  180. "stripvtags(' if(is_array(\\1)) { foreach(\\1 as \\2 => \\3) { ?>','\\4 } } ?>')",
  181. $template
  182. );
  183. $template = preg_replace("/([\n\r\t]*)\{if\s+(.+?)\}([\n\r]*)(.+?)([\n\r]*)\{\/if\}([\n\r\t]*)/ies",
  184. "stripvtags('\\1 if(\\2) { ?>\\3','\\4\\5 } ?>\\6')",
  185. $template
  186. );
  187. }
  188. // 常量替换
  189. $template = preg_replace("/\{([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/s",
  190. "=\\1?>",
  191. $template
  192. );
  193. // 删除 PHP 代码断间多余的空格及换行
  194. $template = preg_replace("/ \?\>[\n\r]*\ // 其他替换
  195. $template = preg_replace("/\"(http)?[\w\.\/:]+\?[^\"]+?&[^\"]+?\"/e",
  196. "transamp('\\0')",
  197. $template
  198. );
  199. $template = preg_replace("/\<script>]*?src=\"(.+?)\".*?\>\s*\<\/script\>/ise",<li> "stripscriptamp('\\1')",<li> $template<li> );<li> $template = preg_replace("/[\n\r\t]*\{block\s+([a-zA-Z0-9_]+)\}(.+?)\{\/block\}/ies",<li> "stripblock('\\1', '\\2')",<li> $template<li> ); <li> // 添加 md5 及过期校验<li> $md5data = md5_file($tplfile);<li> $expireTime = time();<li> $template = "<? if (!class_exists('template')) die('Access Denied');"<li> . "\$template->getInstance()->check('$file', '$md5data', $expireTime);"<li> . "?>\r\n$template"; <li> // 写入缓存文件<li> $cachefile = $this -> _getCacheFile($file);<li> $makepath = $this -> _makepath($cachefile);<li> if ($makepath !== true)<li> $this -> _throwException("无法创建缓存目录 \"$makepath\"");<li> file_put_contents($cachefile, $template);<li> } <li><li> /**<li> * 将路径修正为适合操作系统的形式<li> * <li> * @param string $path 路径名称<li> * @return string <li> */<li> protected function _trimpath($path) {<li> return str_replace(array('/', '\\', '//', '\\\\'), self :: DIR_SEP, $path);<li> } <li><li> /**<li> * 获取模板文件名及路径<li> * <li> * @param string $file 模板文件名称<li> * @return string <li> */<li> protected function _getTplFile($file) {<li> return $this -> _trimpath($this -> _options['template_dir'] . self :: DIR_SEP . $file);<li> } <li><li> /**<li> * 获取模板缓存文件名及路径<li> * <li> * @param string $file 模板文件名称<li> * @return string <li> */<li> protected function _getCacheFile($file) {<li> $file = preg_replace('/\.[a-z0-9\-_]+$/i', '.cache.php', $file);<li> return $this -> _trimpath($this -> _options['cache_dir'] . self :: DIR_SEP . $file);<li> } <li><li> /**<li> * 根据指定的路径创建不存在的文件夹<li> * <li> * @param string $path 路径/文件夹名称<li> * @return string <li> */<li> protected function _makepath($path) {<li> $dirs = explode(self :: DIR_SEP, dirname($this -> _trimpath($path)));<li> $tmp = '';<li> foreach ($dirs as $dir) {<li> $tmp .= $dir . self :: DIR_SEP;<li> if (!file_exists($tmp) && !@mkdir($tmp, 0777))<li> return $tmp;<li> } <li> return true;<li> } <li><li> /**<li> * 抛出一个错误信息<li> * <li> * @param string $message <li> * @return void <li> */<li> protected function _throwException($message) {<li> throw new Exception($message);<li> } <li>} <li><li>?><li><li></script>
复制代码
  1. 模板函数文件
  2. /**
  3. * 模板替换中需要用到的函数
  4. * http://blog.qita.in
  5. */
  6. function transamp($template) {
  7. $template = str_replace('&', '&', $template);
  8. $template = str_replace('&', '&', $template);
  9. $template = str_replace('\"', '"', $template);
  10. return $template;
  11. }
  12. function stripvtags($expr, $statement) {
  13. $expr = str_replace("\\\"", "\"", preg_replace("/\/s", "\\1", $expr));
  14. $statement = str_replace("\\\"", "\"", $statement);
  15. return $expr . $statement;
  16. }
  17. function addquote($var) {
  18. return str_replace("\\\"", "\"", preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
  19. }
  20. function stripscriptamp($s) {
  21. $s = str_replace('&', '&', $s);
  22. return "";
  23. }
  24. function stripblock($var, $s) {
  25. $s = str_replace('\\"', '"', $s);
  26. $s = preg_replace("//", "{\$\\1}", $s);
  27. preg_match_all("//e", $s, $constary);
  28. $constadd = '';
  29. $constary[1] = array_unique($constary[1]);
  30. foreach($constary[1] as $const) {
  31. $constadd .= '$__' . $const .' = ' . $const . ';';
  32. }
  33. $s = preg_replace("//", "{\$__\\1}", $s);
  34. $s = str_replace('?>', "\n\$$var .= $s = str_replace('', "\nEOF;\n", $s);
  35. return "\n$constadd\$$var = ";
  36. }
  37. ?>
复制代码


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn