So that the development and maintenance of web systems more convenient, thereby effectively saving human and material resources, by more and more enterprises of the green squint.
The template engine is an important method of the MVC pattern establishment process, the developer can design a set of meaning tags, through the Technical analysis processing effective data logic processing from the interface template extraction, by reading the meaning of the label to the corresponding business logic processing program, so as to obtain the required data, In the form of template design to show, so that designers can put more energy in the form of expression. Here is my understanding of the template engine and design methods:
It's nice to say. Template engine, is the process of interpreting template data (personal views ^ ^). Through my understanding of the establishment of the station, the site in the show form is nothing more than a single and more than two forms, then we can set up two corresponding tags (such as data, list) to deal with these two situations, the key point is to solve the two kinds of tags of multi-layer nesting problem, basically suitable for the implementation of 80% interface forms.
There are many ways to interpret templates, including string processing (solving nesting problems), regular expressions. Here is the regular expression I choose, the following is my processing method (this article only provides ideas and reference code, may not be used directly).
Template file Resolution class:
Copy Code code as follows:
<?php
/*
* Class: Template parsing Class
* AUTHOR:51JS.COM-ZMM
* date:2011.3.1
* email:304924248@qq.com
* blog:http://www.cnblogs.com/cnzmm/
*/
Class Template {
Public $html, $vars, $bTag, $eTag;
Public $bFlag = ' {', $eFlag = '} ', $pfix = ' zmm: ';
Private $folder, $file;
function __construct ($vars =array ()) {
!empty ($vars) && $this->vars = $vars;
!empty ($GLOBALS [' Cfg_tag_prefix ']) &&
$this->pfix = $GLOBALS [' Cfg_tag_prefix ']. ': ';
$this->btag = $this->bflag. $this->pfix;
$this->etag = $this->bflag. \/'. $this->pfix;
Empty (Tags:: $vars) && Tags:: $vars = & $this->vars;
}
Public Function Loadtpl ($TPL) {
$this->file = $this->gettplpath ($TPL);
Tags:: $file = & $this->file;
if (Is_file ($this->file)) {
if ($this->gettplhtml ()) {
$this->settpltags ();
} else {
Exit (' template file failed to load! ');
}
} else {
Exit (' template file ['. $this->file. '] It doesn't exist! ');
}
}
Private Function Gettplpath ($TPL) {
$this->folder = Website_dirroot.
$GLOBALS [' Cfg_tpl_root '];
return $this->folder. ' /'. $tpl;
}
Private Function gettplhtml () {
$html = self::fmttplhtml (file_get_contents ($this->file));
if (!empty ($html)) {
$callFunc = Tags:: $prefix. ' Syntax ';
$this->html = Tags:: $callFunc ($html, New Template ());
} else {
Exit (' template file content is empty! ');
return true;
}
static public Function fmttplhtml ($html) {
return Preg_replace ('/(R) | \ n) | (t) | (\s{2,})/is ', ', $html);
}
Public Function Register ($vars =array ()) {
if (Is_array ($vars)) {
$this->vars = $vars;
Tags:: $vars = & $this->vars;
}
}
Public Function Display ($bool =false, $name = "", $time =0) {
if (!empty ($this->html)) {
if ($bool &&!empty ($name)) {
if (!is_int ($time)) $time = 600;
$cache = new cache ($time);
$cache->set ($name, $this->html);
}
Echo $this->html; Flush ();
} else {
Exit (' template file content is empty! ');
}
}
Public Function Setassign ($souc, $info) {
if (!empty ($this->html)) {
$this->html = Str_ireplace ($souc, self::fmttplhtml ($info), $this->html);
} else {
Exit (' template file content is empty! ');
}
}
Private Function Settpltags () {
$this->setpaneltags (); $this->settrunktags (); $this->reghatchvars ();
}
Private Function Setpaneltags () {
$rule = $this->btag. ' ([^ '. $this->eflag.] +) \/'. $this->eflag;
Preg_match_all ('/'. $rule. /ism ', $this->html, $out _matches);
$this->transtag ($out _matches, ' Panel '); unset ($out _matches);
}
Private Function Settrunktags () {
$rule = $this->btag. ' (\w+) \s* ([^ '. $this->eflag.] *?)'. $this->eflag.
'((?:(?!'. $this->btag. ') [\s\s]*?| (? R) *) '. $this->etag. ' \\1\s* '. $this->eflag;
Preg_match_all ('/'. $rule. /ism ', $this->html, $out _matches);
$this->transtag ($out _matches, ' trunk '); unset ($out _matches);
}
Private Function Transtag ($result, $type) {
if (!empty ($result [0])) {
Switch ($type) {
Case ' Panel ': {
for ($i = 0; $i < count ($result [0]); $i + +) {
$strTag = Explode (', $result [1][$i], 2);
if (Strpos ($strTag [0], '. ')) {
$itemArg = Explode ('. ', $result [1][$i], 2);
$callFunc = Tags:: $prefix. Ucfirst ($itemArg [0]);
if (method_exists (' Tags ', $callFunc)) {
$html = Tags:: $callFunc (Chop ($ITEMARG [1]));
if ($html!== false) {
$this->html = Str_ireplace ($result [0][$i], $html, $this->html);
}
}
} else {
$rule = ' ^ ([^\s]+) \s* ([\s\s]+) $ ';
Preg_match_all ('/'. $rule. /is ', Trim ($result [1][$i]), $tmp _matches);
$callFunc = Tags:: $prefix. Ucfirst ($tmp _matches[1][0]);
if (method_exists (' Tags ', $callFunc)) {
$html = Tags:: $callFunc ($tmp _matches[2][0]);
if ($html!== false) {
$this->html = Str_ireplace ($result [0][$i], $html, $this->html);
}
} unset ($tmp _matches);
}
} break;
}
Case ' trunk ': {
for ($i = 0; $i < count ($result [0]); $i + +) {
$callFunc = Tags:: $prefix. Ucfirst ($result [1][$i]);
if (method_exists (' Tags ', $callFunc)) {
$html = Tags:: $callFunc ($result [2][$i], $result [3][$i]);
$this->html = Str_ireplace ($result [0][$i], $html, $this->html);
}
} break;
}
Default:break;
}
} else {
return false;
}
}
Private Function Reghatchvars () {
$this->setpaneltags ();
}
function __destruct () {}
}
?>
Tag Resolution class: (currently provides data, list two kinds of label analysis, explain the idea)
Copy Code code as follows:
<?php
/*
* Class: Tag resolution Class
* AUTHOR:51JS.COM-ZMM
* date:2011.3.2
* email:304924248@qq.com
* blog:http://www.cnblogs.com/cnzmm/
*/
Class Tags {
static private $attrs =null;
Static public $file, $vars, $rule, $prefix = ' tag_ ';
static public Function Tag_syntax ($html, $that) {
$rule = $that->btag. ' If\s+ ([^. $that->eflag.] +) \s* '. $that->eflag;
$html = preg_replace ('/'. $rule. /ism ', ' <?php if (\\1) {?> ', $html);
$rule = $that->btag. ' Elseif\s+ ([^. $that->eflag.] +) \s* '. $that->eflag;
$html = preg_replace ('/'. $rule. /ism ', ' <?php} elseif (\\1) {?> ', $html);
$rule = $that->btag. ' else\s* '. $that->eflag;
$html = preg_replace ('/'. $rule. /ism ', ' <?php} else {?> ', $html);
$rule = $that->btag. ' loop\s+ (\s+) \s+ (\s+) \s* '. $that->eflag;
$html = preg_replace ('/'. $rule. /ism ', ' <?php foreach (\\1 as \\2) {?> ', $html);
$rule = $that->btag. ' loop\s+ (\s+) \s+ (\s+) \s+ (\s+) \s* '. $that->eflag;
$html = preg_replace ('/'. $rule. /ism ', ' <?php foreach (\\1 as \\2 => \\3) {?> ', $html);
$rule = $that->etag. ' (if|loop) \s* '. $that->eflag;
$html = preg_replace ('/'. $rule. /ism ', ' <?php}?> ', $html);
$rule = $that->btag. ' php\s* '. $that->eflag. ' ((?:(?!'.
$that->btag. ') [\s\s]*?| (? R) *) '. $that->etag ' php\s* '. $that->eflag;
$html = preg_replace ('/'. $rule. /ism ', ' <?php \\1?> ', $html);
Return Self::tag_execute ($html);
}
static public Function tag_list ($attr, $html) {
if (!empty ($html)) {
if (Self::tag_havetag ($html)) {
Return Self::tag_dealtag ($attr, $html, true);
} else {
Return Self::tag_getdata ($attr, $html, true);
}
} else {
Exit (' tag {list} ' content is empty!) ');
}
}
static public Function Tag_data ($attr, $html) {
if (!empty ($html)) {
if (Self::tag_havetag ($html)) {
Return Self::tag_dealtag ($attr, $html, false);
} else {
Return Self::tag_getdata ($attr, $html, false);
}
} else {
Exit (' tag {data} ' content is empty!) ');
}
}
static public Function Tag_execute ($html) {
Ob_clean (); Ob_start ();
if (!empty (self:: $vars)) {
Is_array (self:: $vars) &&
Extract (self:: $vars, Extr_overwrite);
}
$file _inc = website_dirinc. ' /buffer/'.
MD5 (Uniqid (rand (), true). PHP ';
if ($fp = fopen ($file _inc, ' XB ')) {
Fwrite ($fp, $html);
if (fclose ($fp)) {
Include ($file _inc);
$html = Ob_get_contents ();
} unset ($FP);
} else {
Exit (' Template parsing file generation failed! ');
} Ob_end_clean (); @unlink ($file _inc);
return $html;
}
Static Private Function Tag_havetag ($html) {
$bool _has = false;
$tpl _ins = new Template ();
Self:: $rule = $tpl _ins->btag. ([^ '. $tpl _ins->eflag.] +) \/'. $tpl _ins->eflag;
$bool _has = $bool _has | | Preg_match ('/'. Self:: $rule. ' /ism ', $html);
Self:: $rule = $tpl _ins->btag. (\w+) \s* ([^ '. $tpl _ins->eflag.] *?)'. $tpl _ins->eflag.
'((?:(?!'. $tpl _ins->btag. ') [\s\s]*?| (? R) *) '. $tpl _ins->etag. ' \\1\s* '. $tpl _ins->eflag;
$bool _has = $bool _has | | Preg_match ('/'. Self:: $rule. ' /ism ', $html);
unset ($tpl _ins);
return $bool _has;
}
Static Private Function Tag_dealtag ($attr, $html, $list) {
Preg_match_all ('/'. Self:: $rule. ' /ism ', $html, $out _matches);
if (!empty ($out _matches[0])) {
$child _node = Array ();
for ($i = 0; $i < count ($out _matches[0]); $i + +) {
$child _node[] = $out _matches[3][$i];
$html = Str_ireplace ($out _matches[3][$i], ' {-->>child_node_ '. $i. ' <<--} ', $html);
}
$html = Self::tag_getdata ($attr, $html, $list);
for ($i = 0; $i < count ($out _matches[0]); $i + +) {
$html = Str_ireplace (' {-->>child_node_ '. $i. ' <<--} ', $child _node[$i], $html);
}
Preg_match_all ('/'. Self:: $rule. ' /ism ', $html, $tmp _matches);
if (!empty ($tmp _matches[0])) {
for ($i = 0; $i < count ($tmp _matches[0]); $i + +) {
$callFunc = self:: $prefix. Ucfirst ($tmp _matches[1][$i]);
if (method_exists (' Tags ', $callFunc)) {
$temp = self:: $callFunc ($tmp _matches[2][$i], $tmp _matches[3][$i]);
$html = Str_ireplace ($tmp _matches[0][$i], $temp, $html);
}
}
}
unset ($tmp _matches);
}
unset ($out _matches); return $html;
}
Static Private Function Tag_getdata ($attr, $html, $list =false) {
if (!empty ($attr)) {
$attr _ins = new ATTBT ($attr);
$attr _arr = $attr _ins->attrs;
if (Is_array ($attr _arr)) {
Extract ($attr _arr, extr_overwrite);
$source = table_name ($source, $column);
$rule = ' \[field:\s* (\w+) \s* ([^\]]*?) \s*\/?] ';
Preg_match_all ('/'. $rule. /is ', $html, $out _matches);
$data _str = ';
$data _ins = new Datasql ();
$attr _where = $attr _order = ';
if (!empty ($where)) {
$where = Str_replace (', ', ' and ', $where);
$attr _where = ' where '. $where;
}
if (!empty ($order)) {
$attr _order = ' ORDER by '. $order;
} else {
$fed _name = ';
$fed _ins = $data _ins->getfedneedle ($source);
$fed _cnt = $data _ins->getfedcount ($fed _ins);
for ($i = 0; $i < $fed _cnt; $i + +) {
$fed _flag = $data _ins->getfedflag ($fed _ins, $i);
if (Preg_match ('/auto_increment/ism ', $fed _flag)) {
$fed _name = $data _ins->getfedname ($fed _ins, $i);
Break
}
}
if (!empty ($fed _name))
$attr _order = ' ORDER by '. $fed _name. ' Desc ';
}
if ($list = = True) {
if (Empty ($source) && empty ($sql)) {
Exit (' tag {list} ' must specify the Source property!) ');
}
$attr _rows = $attr _page = ';
if ($rows > 0) {
$attr _rows = ' limit 0, '. $rows;
}
if (!empty ($sql)) {
$data _sql = $sql;
} else {
$data _sql = ' select * from '. $source. ' `'.
$attr _where. $attr _order. $attr _rows;
}
if ($pages = = ' true ' &&!empty ($size)) {
$data _num = $data _ins->getrecnum ($data _sql);
$page _cnt = ceil ($data _num/$size);
Global $page;
if (!isset ($page) | | | $page < 1) $page = 1;
if ($page > $page _cnt) $page = $page _cnt;
$data _sql = ' select * from '. $source. ' '. $attr _where.
$attr _order. ' Limit '. ($page-1) * $size. ', '. $size;
$GLOBALS [' cfg_page_curr '] = $page;
$GLOBALS [' cfg_page_prev '] = $page-1;
$GLOBALS [' cfg_page_next '] = $page + 1;
$GLOBALS [' cfg_page_nums '] = $page _cnt;
if (function_exists (' List_pagelink ')) {
$GLOBALS [' cfg_page_list '] = List_pagelink ($page, $page _cnt, 2);
}
}
$data _idx = 0;
$data _ret = $data _ins->sqlcmdexec ($data _sql);
while ($row = $data _ins->getrecarr ($data _ret)) {
if ($skip > 0 &&!empty ($flag)) {
$data _idx!= 0 &&
$data _idx% $skip = 0 &&
$data _str. = $flag;
}
$data _tmp = $html;
$data _tmp = str_ireplace (' @idx ', $data _idx, $data _tmp);
for ($i = 0; $i < count ($out _matches[0]); $i + +) {
$data _tmp = str_ireplace ($out _matches[0][$i],
$row [$out _matches[1][$i]], $data _tmp);
}
$data _str. = $data _tmp; $data _idx + +;
}
} else {
if (empty ($source)) {
Exit (' tag {data} ' must specify the Source property!) ');
}
$data _sql = ' select * from '. $source.
"$attr _where $attr _order;
$row = $data _ins->getonerec ($data _sql);
if (Is_array ($row)) {
$data _tmp = $html;
for ($i = 0; $i < count ($out _matches[0]); $i + +) {
$data _val = $row [$out _matches[1][$i]];
if (Empty ($out _matches[2][$i])) {
$data _tmp = str_ireplace ($out _matches[0][$i], $data _val, $data _tmp);
} else {
$attr _str = $out _matches[2][$i];
$attr _ins = new ATTBT ($attr _str);
$func _txt = $attr _ins->attrs[' function '];
if (!empty ($func _txt)) {
$func _tmp = Explode (' (', $func _txt);
if (Function_exists ($func _tmp[0])) {
Eval (' $func _ret = '. Str_ireplace (' @me '),
' $data _val. ', $func _txt));
$data _tmp = str_ireplace ($out _matches[0][$i], $func _ret, $data _tmp);
} else {
Exit (' calls a nonexistent function! ');
}
} else {
Exit (' Label settings property is invalid! ');
}
}
}
$data _str. = $data _tmp;
}
}
unset ($data _ins);
return $data _str;
} else {
Exit (' Label settings property is invalid! ');
}
} else {
Exit (' No label properties set! ');
}
}
static public Function __callstatic ($name, $args) {
Exit (' label {'. $name. '} It doesn't exist! ');
}
}
?>