Heim >Backend-Entwicklung >PHP-Tutorial >有关php mvc模式的模板引擎开发经验分享

有关php mvc模式的模板引擎开发经验分享

WBOY
WBOYOriginal
2016-07-25 09:05:291256Durchsuche
  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.')[\S\s]*?|(?R))*)'.$this->eTag.'\\1\s*'.$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 $strTag = explode(' ', $result[1][$i], 2);
  95. if (strpos($strTag[0], '.')) {
  96. $itemArg = explode('.', $result[1][$i], 2);
  97. $callFunc = Tags::$prefix.ucfirst($itemArg[0]);
  98. if (method_exists('Tags', $callFunc)) {
  99. $html = Tags::$callFunc(chop($itemArg[1]));
  100. if ($html !== false) {
  101. $this->html = str_ireplace($result[0][$i], $html, $this->html);
  102. }
  103. }
  104. } else {
  105. $rule = '^([^\s]+)\s*([\S\s]+)$';
  106. preg_match_all('/'.$rule.'/is', trim($result[1][$i]), $tmp_matches);
  107. $callFunc = Tags::$prefix.ucfirst($tmp_matches[1][0]);
  108. if (method_exists('Tags', $callFunc)) {
  109. $html = Tags::$callFunc($tmp_matches[2][0]);
  110. if ($html !== false) {
  111. $this->html = str_ireplace($result[0][$i], $html, $this->html);
  112. }
  113. } unset($tmp_matches);
  114. }
  115. } break;
  116. }
  117. case 'trunk' : {
  118. for ($i = 0; $i $callFunc = Tags::$prefix.ucfirst($result[1][$i]);
  119. if (method_exists('Tags', $callFunc)) {
  120. $html = Tags::$callFunc($result[2][$i], $result[3][$i]);
  121. $this->html = str_ireplace($result[0][$i], $html, $this->html);
  122. }
  123. } break;
  124. }
  125. default: break;
  126. }
  127. } else {
  128. return false;
  129. }
  130. }
  131. private function RegHatchVars() {
  132. $this->SetPanelTags();
  133. }
  134. function __destruct() {}
  135. }
  136. ?>
复制代码

二、标签解析类:(暂时提供data、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.'if\s+([^'.$that->eFlag.']+)\s*'.$that->eFlag;
  14. $html = preg_replace('/'.$rule.'/ism', '', $html);
  15. $rule = $that->bTag.'elseif\s+([^'.$that->eFlag.']+)\s*'.$that->eFlag;
  16. $html = preg_replace('/'.$rule.'/ism', '', $html);
  17. $rule = $that->bTag.'else\s*'.$that->eFlag;
  18. $html = preg_replace('/'.$rule.'/ism', '', $html);
  19. $rule = $that->bTag.'loop\s+(\S+)\s+(\S+)\s*'.$that->eFlag;
  20. $html = preg_replace('/'.$rule.'/ism', '', $html);
  21. $rule = $that->bTag.'loop\s+(\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.'php\s*'.$that->eFlag.'((?:(?!'.
  26. $that->bTag.')[\S\s]*?|(?R))*)'.$that->eTag.'php\s*'.$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.')[\S\s]*?|(?R))*)'.$tpl_ins->eTag.'\\1\s*'.$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 $child_node[] = $out_matches[3][$i];
  87. $html = str_ireplace($out_matches[3][$i], '{-->>child_node_'.$i.'}
  88. $html = self::TAG_GetData($attr, $html, $list);
  89. for ($i = 0; $i $html = str_ireplace('{-->>child_node_'.$i.'}
  90. preg_match_all('/'.self::$rule.'/ism', $html, $tmp_matches);
  91. if (!empty($tmp_matches[0])) {
  92. for ($i = 0; $i $callFunc = self::$prefix.ucfirst($tmp_matches[1][$i]);
  93. if (method_exists('Tags', $callFunc)) {
  94. $temp = self::$callFunc($tmp_matches[2][$i], $tmp_matches[3][$i]);
  95. $html = str_ireplace($tmp_matches[0][$i], $temp, $html);
  96. }
  97. }
  98. }
  99. unset($tmp_matches);
  100. }
  101. unset($out_matches); return $html;
  102. }
  103. static private function TAG_GetData($attr, $html, $list=false) {
  104. if (!empty($attr)) {
  105. $attr_ins = new Attbt($attr);
  106. $attr_arr = $attr_ins->attrs;
  107. if (is_array($attr_arr)) {
  108. extract($attr_arr, EXTR_OVERWRITE);
  109. $source = table_name($source, $column);
  110. $rule = '\[field:\s*(\w+)\s*([^\]]*?)\s*\/?]';
  111. preg_match_all('/'.$rule.'/is', $html, $out_matches);
  112. $data_str = '';
  113. $data_ins = new DataSql();
  114. $attr_where = $attr_order = '';
  115. if (!empty($where)) {
  116. $where = str_replace(',', ' and ', $where);
  117. $attr_where = ' where '. $where;
  118. }
  119. if (!empty($order)) {
  120. $attr_order = ' order by '.$order;
  121. } else {
  122. $fed_name = '';
  123. $fed_ins = $data_ins->GetFedNeedle($source);
  124. $fed_cnt = $data_ins->GetFedCount($fed_ins);
  125. for ($i = 0; $i $fed_flag = $data_ins->GetFedFlag($fed_ins, $i);
  126. if (preg_match('/auto_increment/ism', $fed_flag)) {
  127. $fed_name = $data_ins->GetFedName($fed_ins, $i);
  128. break;
  129. }
  130. }
  131. if (!empty($fed_name))
  132. $attr_order = ' order by '.$fed_name.' desc';
  133. }
  134. if ($list == true) {
  135. if (empty($source) && empty($sql)) {
  136. exit('标签{list}必须指定source属性!');
  137. }
  138. $attr_rows = $attr_page = '';
  139. if ($rows > 0) {
  140. $attr_rows = ' limit 0,'.$rows;
  141. }
  142. if (!empty($sql)) {
  143. $data_sql = $sql;
  144. } else {
  145. $data_sql = 'select * from `'.$source.'`'.
  146. $attr_where.$attr_order.$attr_rows;
  147. }
  148. if ($pages=='true' && !empty($size)) {
  149. $data_num = $data_ins->GetRecNum($data_sql);
  150. $page_cnt = ceil($data_num / $size);
  151. global $page;
  152. if (!isset($page) || $page if ($page > $page_cnt) $page = $page_cnt;
  153. $data_sql = 'select * from `'.$source.'`'.$attr_where.
  154. $attr_order.' limit '.($page-1) * $size.','.$size;
  155. $GLOBALS['cfg_page_curr'] = $page;
  156. $GLOBALS['cfg_page_prev'] = $page - 1;
  157. $GLOBALS['cfg_page_next'] = $page + 1;
  158. $GLOBALS['cfg_page_nums'] = $page_cnt;
  159. if (function_exists('list_pagelink')) {
  160. $GLOBALS['cfg_page_list'] = list_pagelink($page, $page_cnt, 2);
  161. }
  162. }
  163. $data_idx = 0;
  164. $data_ret = $data_ins->SqlCmdExec($data_sql);
  165. while ($row = $data_ins->GetRecArr($data_ret)) {
  166. if ($skip > 0 && !empty($flag)) {
  167. $data_idx != 0 &&
  168. $data_idx % $skip == 0 &&
  169. $data_str .= $flag;
  170. }
  171. $data_tmp = $html;
  172. $data_tmp = str_ireplace('@idx', $data_idx, $data_tmp);
  173. for ($i = 0; $i $data_tmp = str_ireplace($out_matches[0][$i],
  174. $row[$out_matches[1][$i]], $data_tmp);
  175. }
  176. $data_str .= $data_tmp; $data_idx ++;
  177. }
  178. } else {
  179. if (empty($source)) {
  180. exit('标签{data}必须指定source属性!');
  181. }
  182. $data_sql = 'select * from `'.$source.
  183. '`'.$attr_where.$attr_order;
  184. $row = $data_ins->GetOneRec($data_sql);
  185. if (is_array($row)) {
  186. $data_tmp = $html;
  187. for ($i = 0; $i $data_val = $row[$out_matches[1][$i]];
  188. if (empty($out_matches[2][$i])) {
  189. $data_tmp = str_ireplace($out_matches[0][$i], $data_val, $data_tmp);
  190. } else {
  191. $attr_str = $out_matches[2][$i];
  192. $attr_ins = new Attbt($attr_str);
  193. $func_txt = $attr_ins->attrs['function'];
  194. if (!empty($func_txt)) {
  195. $func_tmp = explode('(', $func_txt);
  196. if (function_exists($func_tmp[0])) {
  197. eval('$func_ret ='.str_ireplace('@me',
  198. '\''.$data_val.'\'', $func_txt));
  199. $data_tmp = str_ireplace($out_matches[0][$i], $func_ret, $data_tmp);
  200. } else {
  201. exit('调用了不存在的函数!');
  202. }
  203. } else {
  204. exit('标签设置属性无效!');
  205. }
  206. }
  207. }
  208. $data_str .= $data_tmp;
  209. }
  210. }
  211. unset($data_ins);
  212. return $data_str;
  213. } else {
  214. exit('标签设置属性无效!');
  215. }
  216. } else {
  217. exit('没有设置标签属性!');
  218. }
  219. }
  220. static public function __callStatic($name, $args) {
  221. exit('标签{'.$name.'}不存在!');
  222. }
  223. }
  224. ?>
复制代码


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