Share the development experience of the MVC template engine in PHP

Source: Internet
Author: User
Tags php foreach
MVC is the abbreviation of Model, View, and Controller. the purpose of MVC mode in PHP is to achieve the division of functions of the Web system, in general, business logic processing is separated from the user interface view. It makes the development and maintenance of Web systems more convenient, thus effectively saving manpower and material resources, attracting more and more enterprises.

The template engine is an important method for establishing the MVC model. developers can design a set of labels that give meanings and extract data logic processing from the interface template effectively through technical parsing, by interpreting the meaning of the tag, the control is submitted to the corresponding business logic processing program to obtain the required data and present it as a template design, allows the designer to focus more on the presentation form. The following is my understanding and design of the template engine:

The template engine is actually the process of interpreting template data (personal opinion ^ ). Based on my understanding of website construction, the website display form is simply summarized into single and multiple forms, so we can set two corresponding tags (such as data and list) to deal with these two situations, the key point is to solve the problem of multi-layer nesting of the two labels, which is basically suitable for implementing the 80% interface form.

There are many methods to interpret templates, including string processing (to solve nesting is a little complicated) and regular expressions. Here I use a regular expression. below is my solution (this article only provides ideas and reference code, and may not be used directly ).

Template file parsing class:

The code is as follows:


/*
* 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 loading failed! ');
}
} Else {
Exit ('Template file ['. $ this-> file.'] does not 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 blank! ');
} 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 blank! ');
}
}
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 blank! ');
}
}
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 parsing: (currently, the data and list tags are provided for parsing)

The code is as follows:


/*
* Class: tag parsing 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 ',' ', $ Html );
$ Rule = $ that-> bTag. 'elseif \ s + ([^ '. $ that-> eFlag.'] +) \ s * '. $ that-> eFlag;
$ Html = preg_replace ('/'. $ rule. '/ism ',' ', $ Html );
$ Rule = $ that-> bTag. 'else \ s * '. $ that-> eFlag;
$ Html = preg_replace ('/'. $ rule. '/ism ',' ', $ Html );
$ Rule = $ that-> bTag. 'loop \ s + (\ S +) \ s * '. $ that-> eFlag;
$ Html = preg_replace ('/'. $ rule. '/ism ',' ', $ Html );
$ Rule = $ that-> bTag. 'loop \ s + (\ S +) \ s *'. $ that-> eFlag;
$ Html = preg_replace ('/'. $ rule. '/ism ',' \ 3) {?> ', $ Html );
$ Rule = $ that-> eTag. '(if | loop) \ s *'. $ that-> eFlag;
$ Html = preg_replace ('/'. $ rule. '/ism ',' ', $ Html );
$ Rule = $ that-> bTag. 'php \ s * '. $ that-> eFlag .'((? :(?! '.
$ That-> bTag. ') [\ S \ s] *? | (? R) *) '. $ that-> eTag. 'php \ s *'. $ that-> eFlag;
$ Html = preg_replace ('/'. $ rule. '/ism ',' ', $ 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 (the content of 'tag {list} is blank! ');
}
}
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 blank! ');
}
}
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 attribute! ');
}
$ 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 attribute! ');
}
$ 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 ('a nonexistent function is called! ');
}
} Else {
Exit ('tag setting property is invalid! ');
}
}
}
$ Data_str. = $ data_tmp;
}
}
Unset ($ data_ins );
Return $ data_str;
} Else {
Exit ('tag setting property is invalid! ');
}
} Else {
Exit ('no tag property is set! ');
}
}
Static public function _ callStatic ($ name, $ args ){
Exit ('tag {'. $ name.'} does not exist! ');
}
}
?>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.