Home  >  Article  >  Backend Development  >  Sharing experience in template engine development in PHP MVC mode

Sharing experience in template engine development in PHP MVC mode

WBOY
WBOYOriginal
2016-07-25 09:05:291223browse
  1. /*
  2. * class: 模板解析类
  3. * author: 51JS.COM-ZMM
  4. * date: 2011.3.1
  5. * email: 304924248@qq.com
  6. * blog: http://www.cnblogs.com/cnzmm/
  7. * link: http://bbs.it-home.org
  8. */
  9. class Template {
  10. public $html, $vars, $bTag, $eTag;
  11. public $bFlag='{', $eFlag='}', $pfix='zmm:';
  12. private $folder, $file;
  13. function __construct($vars=array()) {
  14. !empty($vars) && $this->vars = $vars;
  15. !empty($GLOBALS['cfg_tag_prefix']) &&
  16. $this->pfix = $GLOBALS['cfg_tag_prefix'].':';
  17. $this->bTag = $this->bFlag.$this->pfix;
  18. $this->eTag = $this->bFlag.'/'.$this->pfix;
  19. empty(Tags::$vars) && Tags::$vars = &$this->vars;
  20. }
  21. public function LoadTpl($tpl) {
  22. $this->file = $this->GetTplPath($tpl);
  23. Tags::$file = &$this->file;
  24. if (is_file($this->file)) {
  25. if ($this->GetTplHtml()) {
  26. $this->SetTplTags();
  27. } else {
  28. exit('模板文件加载失败!');
  29. }
  30. } else {
  31. exit('模板文件['.$this->file.']不存在!');
  32. }
  33. }
  34. private function GetTplPath($tpl) {
  35. $this->folder = WEBSITE_DIRROOT.
  36. $GLOBALS['cfg_tpl_root'];
  37. return $this->folder.'/'.$tpl;
  38. }
  39. private function GetTplHtml() {
  40. $html = self::FmtTplHtml(file_get_contents($this->file));
  41. if (!empty($html)) {
  42. $callFunc = Tags::$prefix.'Syntax';
  43. $this->html = Tags::$callFunc($html, new Template());
  44. } else {
  45. exit('模板文件内容为空!');
  46. } return true;
  47. }
  48. static public function FmtTplHtml($html) {
  49. return preg_replace('/(r)|(n)|(t)|(s{2,})/is', '', $html);
  50. }
  51. public function Register($vars=array()) {
  52. if (is_array($vars)) {
  53. $this->vars = $vars;
  54. Tags::$vars = &$this->vars;
  55. }
  56. }
  57. public function Display($bool=false, $name="", $time=0) {
  58. if (!empty($this->html)) {
  59. if ($bool && !empty($name)) {
  60. if (!is_int($time)) $time = 600;
  61. $cache = new Cache($time);
  62. $cache->Set($name, $this->html);
  63. }
  64. echo $this->html; flush();
  65. } else {
  66. exit('模板文件内容为空!');
  67. }
  68. }
  69. public function SetAssign($souc, $info) {
  70. if (!empty($this->html)) {
  71. $this->html = str_ireplace($souc, self::FmtTplHtml($info), $this->html);
  72. } else {
  73. exit('模板文件内容为空!');
  74. }
  75. }
  76. private function SetTplTags() {
  77. $this->SetPanelTags(); $this->SetTrunkTags(); $this->RegHatchVars();
  78. }
  79. private function SetPanelTags() {
  80. $rule = $this->bTag.'([^'.$this->eFlag.']+)/'.$this->eFlag;
  81. preg_match_all('/'.$rule.'/ism', $this->html, $out_matches);
  82. $this->TransTag($out_matches, 'panel'); unset($out_matches);
  83. }
  84. private function SetTrunkTags() {
  85. $rule = $this->bTag.'(w+)s*([^'.$this->eFlag.']*?)'.$this->eFlag.
  86. '((?:(?!'.$this->bTag.')[Ss]*?|(?R))*)'.$this->eTag.'\1s*'.$this->eFlag;
  87. preg_match_all('/'.$rule.'/ism', $this->html, $out_matches);
  88. $this->TransTag($out_matches, 'trunk'); unset($out_matches);
  89. }
  90. private function TransTag($result, $type) {
  91. if (!empty($result[0])) {
  92. switch ($type) {
  93. case 'panel' : {
  94. for ($i = 0; $i < count($result[0]); $i ++) {
  95. $strTag = explode(' ', $result[1][$i], 2);
  96. if (strpos($strTag[0], '.')) {
  97. $itemArg = explode('.', $result[1][$i], 2);
  98. $callFunc = Tags::$prefix.ucfirst($itemArg[0]);
  99. if (method_exists('Tags', $callFunc)) {
  100. $html = Tags::$callFunc(chop($itemArg[1]));
  101. if ($html !== false) {
  102. $this->html = str_ireplace($result[0][$i], $html, $this->html);
  103. }
  104. }
  105. } else {
  106. $rule = '^([^s]+)s*([Ss]+)$';
  107. preg_match_all('/'.$rule.'/is', trim($result[1][$i]), $tmp_matches);
  108. $callFunc = Tags::$prefix.ucfirst($tmp_matches[1][0]);
  109. if (method_exists('Tags', $callFunc)) {
  110. $html = Tags::$callFunc($tmp_matches[2][0]);
  111. if ($html !== false) {
  112. $this->html = str_ireplace($result[0][$i], $html, $this->html);
  113. }
  114. } unset($tmp_matches);
  115. }
  116. } break;
  117. }
  118. case 'trunk' : {
  119. for ($i = 0; $i < count($result[0]); $i ++) {
  120. $callFunc = Tags::$prefix.ucfirst($result[1][$i]);
  121. if (method_exists('Tags', $callFunc)) {
  122. $html = Tags::$callFunc($result[2][$i], $result[3][$i]);
  123. $this->html = str_ireplace($result[0][$i], $html, $this->html);
  124. }
  125. } break;
  126. }
  127. default: break;
  128. }
  129. } else {
  130. return false;
  131. }
  132. }
  133. private function RegHatchVars() {
  134. $this->SetPanelTags();
  135. }
  136. function __destruct() {}
  137. }
  138. ?>
复制代码

2. Tag parsing class: (Temporarily providing two tag parsing ideas: data and list)

  1. /*
  2. * class: 标签解析类
  3. * author: 51JS.COM-ZMM
  4. * date: 2011.3.2
  5. * email: 304924248@qq.com
  6. * blog: http://www.cnblogs.com/cnzmm/
  7. * link: http://bbs.it-home.org
  8. */
  9. class Tags {
  10. static private $attrs=null;
  11. static public $file, $vars, $rule, $prefix='TAG_';
  12. static public function TAG_Syntax($html, $that) {
  13. $rule = $that->bTag.'ifs+([^'.$that->eFlag.']+)s*'.$that->eFlag;
  14. $html = preg_replace('/'.$rule.'/ism', '', $html);
  15. $rule = $that->bTag.'elseifs+([^'.$that->eFlag.']+)s*'.$that->eFlag;
  16. $html = preg_replace('/'.$rule.'/ism', '', $html);
  17. $rule = $that->bTag.'elses*'.$that->eFlag;
  18. $html = preg_replace('/'.$rule.'/ism', '', $html);
  19. $rule = $that->bTag.'loops+(S+)s+(S+)s*'.$that->eFlag;
  20. $html = preg_replace('/'.$rule.'/ism', '', $html);
  21. $rule = $that->bTag.'loops+(S+)s+(S+)s+(S+)s*'.$that->eFlag;
  22. $html = preg_replace('/'.$rule.'/ism', ' \3) { ?>', $html);
  23. $rule = $that->eTag.'(if|loop)s*'.$that->eFlag;
  24. $html = preg_replace('/'.$rule.'/ism', '', $html);
  25. $rule = $that->bTag.'phps*'.$that->eFlag.'((?:(?!'.
  26. $that->bTag.')[Ss]*?|(?R))*)'.$that->eTag.'phps*'.$that->eFlag;
  27. $html = preg_replace('/'.$rule.'/ism', '', $html);
  28. return self::TAG_Execute($html);
  29. }
  30. static public function TAG_List($attr, $html) {
  31. if (!empty($html)) {
  32. if (self::TAG_HaveTag($html)) {
  33. return self::TAG_DealTag($attr, $html, true);
  34. } else {
  35. return self::TAG_GetData($attr, $html, true);
  36. }
  37. } else {
  38. exit('标签{list}的内容为空!');
  39. }
  40. }
  41. static public function TAG_Data($attr, $html) {
  42. if (!empty($html)) {
  43. if (self::TAG_HaveTag($html)) {
  44. return self::TAG_DealTag($attr, $html, false);
  45. } else {
  46. return self::TAG_GetData($attr, $html, false);
  47. }
  48. } else {
  49. exit('标签{data}的内容为空!');
  50. }
  51. }
  52. static public function TAG_Execute($html) {
  53. ob_clean(); ob_start();
  54. if (!empty(self::$vars)) {
  55. is_array(self::$vars) &&
  56. extract(self::$vars, EXTR_OVERWRITE);
  57. }
  58. $file_inc = WEBSITE_DIRINC.'/buffer/'.
  59. md5(uniqid(rand(), true)).'.php';
  60. if ($fp = fopen($file_inc, 'xb')) {
  61. fwrite($fp, $html);
  62. if (fclose($fp)) {
  63. include($file_inc);
  64. $html = ob_get_contents();
  65. } unset($fp);
  66. } else {
  67. exit('模板解析文件生成失败!');
  68. } ob_end_clean(); @unlink($file_inc);
  69. return $html;
  70. }
  71. static private function TAG_HaveTag($html) {
  72. $bool_has = false;
  73. $tpl_ins = new Template();
  74. self::$rule = $tpl_ins->bTag.'([^'.$tpl_ins->eFlag.']+)/'.$tpl_ins->eFlag;
  75. $bool_has = $bool_has || preg_match('/'.self::$rule.'/ism', $html);
  76. self::$rule = $tpl_ins->bTag.'(w+)s*([^'.$tpl_ins->eFlag.']*?)'.$tpl_ins->eFlag.
  77. '((?:(?!'.$tpl_ins->bTag.')[Ss]*?|(?R))*)'.$tpl_ins->eTag.'\1s*'.$tpl_ins->eFlag;
  78. $bool_has = $bool_has || preg_match('/'.self::$rule.'/ism', $html);
  79. unset($tpl_ins);
  80. return $bool_has;
  81. }
  82. static private function TAG_DealTag($attr, $html, $list) {
  83. preg_match_all('/'.self::$rule.'/ism', $html, $out_matches);
  84. if (!empty($out_matches[0])) {
  85. $child_node = array();
  86. for ($i = 0; $i < count($out_matches[0]); $i ++) {
  87. $child_node[] = $out_matches[3][$i];
  88. $html = str_ireplace($out_matches[3][$i], '{-->>child_node_'.$i.'<<--}', $html);
  89. }
  90. $html = self::TAG_GetData($attr, $html, $list);
  91. for ($i = 0; $i < count($out_matches[0]); $i ++) {
  92. $html = str_ireplace('{-->>child_node_'.$i.'<<--}', $child_node[$i], $html);
  93. }
  94. preg_match_all('/'.self::$rule.'/ism', $html, $tmp_matches);
  95. if (!empty($tmp_matches[0])) {
  96. for ($i = 0; $i < count($tmp_matches[0]); $i ++) {
  97. $callFunc = self::$prefix.ucfirst($tmp_matches[1][$i]);
  98. if (method_exists('Tags', $callFunc)) {
  99. $temp = self::$callFunc($tmp_matches[2][$i], $tmp_matches[3][$i]);
  100. $html = str_ireplace($tmp_matches[0][$i], $temp, $html);
  101. }
  102. }
  103. }
  104. unset($tmp_matches);
  105. }
  106. unset($out_matches); return $html;
  107. }
  108. static private function TAG_GetData($attr, $html, $list=false) {
  109. if (!empty($attr)) {
  110. $attr_ins = new Attbt($attr);
  111. $attr_arr = $attr_ins->attrs;
  112. if (is_array($attr_arr)) {
  113. extract($attr_arr, EXTR_OVERWRITE);
  114. $source = table_name($source, $column);
  115. $rule = '[field:s*(w+)s*([^]]*?)s*/?]';
  116. preg_match_all('/'.$rule.'/is', $html, $out_matches);
  117. $data_str = '';
  118. $data_ins = new DataSql();
  119. $attr_where = $attr_order = '';
  120. if (!empty($where)) {
  121. $where = str_replace(',', ' and ', $where);
  122. $attr_where = ' where '. $where;
  123. }
  124. if (!empty($order)) {
  125. $attr_order = ' order by '.$order;
  126. } else {
  127. $fed_name = '';
  128. $fed_ins = $data_ins->GetFedNeedle($source);
  129. $fed_cnt = $data_ins->GetFedCount($fed_ins);
  130. for ($i = 0; $i < $fed_cnt; $i ++) {
  131. $fed_flag = $data_ins->GetFedFlag($fed_ins, $i);
  132. if (preg_match('/auto_increment/ism', $fed_flag)) {
  133. $fed_name = $data_ins->GetFedName($fed_ins, $i);
  134. break;
  135. }
  136. }
  137. if (!empty($fed_name))
  138. $attr_order = ' order by '.$fed_name.' desc';
  139. }
  140. if ($list == true) {
  141. if (empty($source) && empty($sql)) {
  142. exit('标签{list}必须指定source属性!');
  143. }
  144. $attr_rows = $attr_page = '';
  145. if ($rows > 0) {
  146. $attr_rows = ' limit 0,'.$rows;
  147. }
  148. if (!empty($sql)) {
  149. $data_sql = $sql;
  150. } else {
  151. $data_sql = 'select * from `'.$source.'`'.
  152. $attr_where.$attr_order.$attr_rows;
  153. }
  154. if ($pages=='true' && !empty($size)) {
  155. $data_num = $data_ins->GetRecNum($data_sql);
  156. $page_cnt = ceil($data_num / $size);
  157. global $page;
  158. if (!isset($page) || $page < 1) $page = 1;
  159. if ($page > $page_cnt) $page = $page_cnt;
  160. $data_sql = 'select * from `'.$source.'`'.$attr_where.
  161. $attr_order.' limit '.($page-1) * $size.','.$size;
  162. $GLOBALS['cfg_page_curr'] = $page;
  163. $GLOBALS['cfg_page_prev'] = $page - 1;
  164. $GLOBALS['cfg_page_next'] = $page + 1;
  165. $GLOBALS['cfg_page_nums'] = $page_cnt;
  166. if (function_exists('list_pagelink')) {
  167. $GLOBALS['cfg_page_list'] = list_pagelink($page, $page_cnt, 2);
  168. }
  169. }
  170. $data_idx = 0;
  171. $data_ret = $data_ins->SqlCmdExec($data_sql);
  172. while ($row = $data_ins->GetRecArr($data_ret)) {
  173. if ($skip > 0 && !empty($flag)) {
  174. $data_idx != 0 &&
  175. $data_idx % $skip == 0 &&
  176. $data_str .= $flag;
  177. }
  178. $data_tmp = $html;
  179. $data_tmp = str_ireplace('@idx', $data_idx, $data_tmp);
  180. for ($i = 0; $i < count($out_matches[0]); $i ++) {
  181. $data_tmp = str_ireplace($out_matches[0][$i],
  182. $row[$out_matches[1][$i]], $data_tmp);
  183. }
  184. $data_str .= $data_tmp; $data_idx ++;
  185. }
  186. } else {
  187. if (empty($source)) {
  188. exit('标签{data}必须指定source属性!');
  189. }
  190. $data_sql = 'select * from `'.$source.
  191. '`'.$attr_where.$attr_order;
  192. $row = $data_ins->GetOneRec($data_sql);
  193. if (is_array($row)) {
  194. $data_tmp = $html;
  195. for ($i = 0; $i < count($out_matches[0]); $i ++) {
  196. $data_val = $row[$out_matches[1][$i]];
  197. if (empty($out_matches[2][$i])) {
  198. $data_tmp = str_ireplace($out_matches[0][$i], $data_val, $data_tmp);
  199. } else {
  200. $attr_str = $out_matches[2][$i];
  201. $attr_ins = new Attbt($attr_str);
  202. $func_txt = $attr_ins->attrs['function'];
  203. if (!empty($func_txt)) {
  204. $func_tmp = explode('(', $func_txt);
  205. if (function_exists($func_tmp[0])) {
  206. eval('$func_ret ='.str_ireplace('@me',
  207. '''.$data_val.''', $func_txt));
  208. $data_tmp = str_ireplace($out_matches[0][$i], $func_ret, $data_tmp);
  209. } else {
  210. exit('调用了不存在的函数!');
  211. }
  212. } else {
  213. exit('标签设置属性无效!');
  214. }
  215. }
  216. }
  217. $data_str .= $data_tmp;
  218. }
  219. }
  220. unset($data_ins);
  221. return $data_str;
  222. } else {
  223. exit('标签设置属性无效!');
  224. }
  225. } else {
  226. exit('没有设置标签属性!');
  227. }
  228. }
  229. static public function __callStatic($name, $args) {
  230. exit('标签{'.$name.'}不存在!');
  231. }
  232. }
  233. ?>
复制代码


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn