PHP--关于模板的原理和解析

来源:互联网 发布:深圳富士康java 编辑:程序博客网 时间:2024/06/05 13:48

将PHP代码和静态HTML代码进行分离,使代码的可读性和维护性得到显著提高。

使用模板引擎:

    我们所说的模板是Web模板,是主要由HTML标记组成的语言来编写的页面,但也有如何表示包含动态生成内容的方式(解析标签)。模板引擎是一种软件库,允许我们从模板生成HTML代码,并指定要包含的动态内容。

  模板引擎的特点:

  1.鼓励分离:让更个系统的可读性和维护性得到提高。
  2.促进分工:使得程序员和美工去专心处理自己的设计。
  3.比PHP更容易解析:编译文件和缓存文件加载更快、占资源更少。
  4.增加安全性:可限制模板设计师进行不安全的操作的能力避免误删误访问等。

模板处理的流程图

  

 

创建模板:

  1、创建初始模板所需要的文件夹和文件。

  a) index.php主文件,用于编写业务逻辑。
  b) template.inc.php模板初始化文件,用于初始模版信息。
  c) templates目录存放所有的模板文件。
  d) templates_c目录存放所有编译文件。
  e) cache目录存放所有缓存文件。
  f) includes目录存放所有的类文件。
  g) config目录存放模板系统变量配置文件。

  

  以下是源码:

主文件 index.php  

<?php   //index.php  //设置编码为UTF-8  header('Content-Type:text/html;Charset=utf-8');  //网站根目录  define('ROOT_PATH', dirname(__FILE__));  //存放模板文件夹  define('TPL_DIR', ROOT_PATH.'/templates/');  //编译文件夹  define('TPL_C_DIR', ROOT_PATH.'/templates_c/');  //缓存文件夹  define('CACHE_DIR', ROOT_PATH.'/cache/');  //定义缓存状态  define('IS_CACHE',true);  //设置缓存状态开关  IS_CACHE ? ob_start() : null;  include ROOT_PATH.'/includes/Templates.class.php';  $_name = '方块李';        $array = array(1,2,3,4,5,6);    $_tpl = new Templates();    $_tpl->assign('name', $_name);    $_tpl->assign('a', 5>4);    $_tpl->assign('array', $array);    //显示    $_tpl->display('index.tpl');?>


模板文件 HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title><!--{webname}--></title> </head><body>{include "test.php"}<!-- 这是HTML的注释 -->{#}这是一条PHP的注释,在HTML页面里是不显示的,只会在生成的编译文件里显示{#}我将被index.php导入{$name}这个标签必须经过Parser.class.php这个解析类来解析它1<br />这里的内容改变了,为什么?<br />{if $a}显示一号皮肤{else}显示二号皮肤{/if}<br />{foreach $array(key,value)}{@key}....{@value} <br />{/foreach}</body></html>


模板类:

 //Templates.class.php  class Templates {    //创建一个存放数组的字段    private $_vars = array();    private $_config = array();    //创建一个构造方法    public function __construct(){        if(!is_dir(TPL_DIR) || !is_dir(TPL_C_DIR) || !is_dir(CACHE_DIR) ){            exit('ERROR:模板文件夹或者编译文件夹或者缓存文件夹没有创建!');        }        //获取系统变量        $_sxe = simplexml_load_file(ROOT_PATH.'/config/profile.xml');        $_taglib = $_sxe->xpath('/root/taglib');        foreach($_taglib as $_tag){            $this->_config["$_tag->name"] = $_tag->value;        }    }            //创建变量注入方法    /**     * assign()变量注入方法     * @param  $_var 要注入的变量名,对应.tpl文件中的需要替换的变量     * @param  $_values 要注入的变量值     */    public function assign($_var,$_values){        if(isset($_var) && !empty($_var)){            $this->_vars[$_var] = $_values;                     }else{            exit('ERROR:请设置变量名!');        }             }              //创建一个显示方法,用来显示编译后的文件    public function display($_file){        //设置模板文件的路径        $_tplFile = TPL_DIR.$_file;        //判断模板文件是否存在        if(!file_exists($_tplFile)){            exit('ERROR:模板文件不存在');        }        //设置编译文件名        $_parFile  = TPL_C_DIR.md5($_file).$_file.'.php';        //设置缓存文件名        $_cacheFile = CACHE_DIR.md5($_file).$_file.'.html';        //判断缓存状态        if(IS_CACHE){            //判断缓存文件是否存在            if(file_exists($_cacheFile) && file_exists($_parFile)){                //是否修改过编译文件或者模板文件                if(filemtime($_cacheFile)>=filemtime($_parFile) && filemtime($_parFile)>filemtime($_tplFile)){                    echo '以下是缓存文件内容';                    echo "<br />";                    include $_cacheFile;                    return;                }            }        }        //判断编译文件是否存在,模板文件是否修改过        if(!file_exists($_parFile) || (filemtime($_parFile) < filemtime($_tplFile))){                         //引入模板解析类            require ROOT_PATH.'/includes/Parser.class.php';            //实例化对象,生成编译文件            $_parser = new Parser($_tplFile);//模板文件            $_parser->compile($_parFile);//编译后文件                     }         //载入编译文件        include $_parFile;        if(IS_CACHE){            //生成缓存文件            file_put_contents($_cacheFile, ob_get_contents());            //清除缓冲区            ob_end_clean();            //载入缓存文件            include $_cacheFile;        }      }}


解析类:


//Parser.class.php    class Parser {        //获取模板内容        private $_tpl;        //构造方法,初始化模板        public function __construct($_tplFile){            //判断文件是否存在            if(!$this->_tpl = file_get_contents($_tplFile)){                exit('ERROR:读取模板出错!');            }                     }                 //解析普通变量        private function parVar(){            $_pattern = '/\{\$([\w]+)\}/';            if (preg_match($_pattern,$this->_tpl)) {                $this->_tpl = preg_replace($_pattern,"<?php echo \$this->_vars['$1'] ?>",$this->_tpl);            }        }        //解析IF条件语句        private function parIf(){            //开头if模式            $_patternIf = '/\{if\s+\$([\w]+)\}/';            //结尾if模式            $_patternEnd = '/\{\/if\}/';            //else模式            $_patternElse = '/\{else\}/';            //判断if是否存在            if(preg_match($_patternIf, $this->_tpl)){                //判断是否有if结尾                if(preg_match($_patternEnd, $this->_tpl)){                    //替换开头IF                    $this->_tpl = preg_replace($_patternIf, "<?php if(\$this->_vars['$1']){ ?>", $this->_tpl);                    //替换结尾IF                    $this->_tpl = preg_replace($_patternEnd, "<?php } ?>", $this->_tpl);                    //判断是否有else                    if(preg_match($_patternElse, $this->_tpl)){                        //替换else                        $this->_tpl = preg_replace($_patternElse, "<?php }else{ ?>", $this->_tpl);                    }                }else{                    exit('ERROR:语句没有关闭!');                }            }        }        //解析foreach        private function parForeach(){            $_patternForeach = '/\{foreach\s+\$(\w+)\((\w+),(\w+)\)\}/';            $_patternEndForeach = '/\{\/foreach\}/';            //foreach里的值            $_patternVar = '/\{@(\w+)\}/';            //判断是否存在            if(preg_match($_patternForeach, $this->_tpl)){                //判断结束标志                if(preg_match($_patternEndForeach, $this->_tpl)){                    //替换开头                    $this->_tpl = preg_replace($_patternForeach, "<?php foreach(\$this->_vars['$1'] as \$$2=>\$$3){?>", $this->_tpl);                    //替换结束                    $this->_tpl = preg_replace($_patternEndForeach, "<?php } ?>", $this->_tpl);                    //替换值                    $this->_tpl = preg_replace($_patternVar, "<?php echo \$$1?>", $this->_tpl);                }else{                    exit('ERROR:Foreach语句没有关闭');                }            }        }        //解析include        private function parInclude(){            $_pattern = '/\{include\s+\"(.*)\"\}/';            if(preg_match($_pattern, $this->_tpl,$_file)){                //判断头文件是否存在                if(!file_exists($_file[1]) || empty($_file[1])){                    exit('ERROR:包含文件不存在!');                }                //替换内容                $this->_tpl = preg_replace($_pattern, "<?php include '$1';?>", $this->_tpl);            }        }        //解析系统变量        private function configVar(){            $_pattern = '/<!--\{(\w+)\}-->/';            if(preg_match($_pattern, $this->_tpl,$_file)){                $this->_tpl = preg_replace($_pattern,"<?php echo \$this->_config['$1'] ?>", $this->_tpl);                             }        }                 //解析单行PHP注释        private function parCommon(){            $_pattern = '/\{#\}(.*)\{#\}/';            if(preg_match($_pattern, $this->_tpl)){                $this->_tpl = preg_replace($_pattern, "<?php /*($1) */?>", $this->_tpl);            }        }                          //生成编译文件        public function compile($_parFile){            //解析模板变量            $this->parVar();            //解析IF            $this->parIf();            //解析注释            $this->parCommon();            //解析Foreach            $this->parForeach();            //解析include            $this->parInclude();            //解析系统变量            $this->configVar();            //生成编译文件            if(!file_put_contents($_parFile, $this->_tpl)){                exit('ERROR:编译文件生成失败!');            }        }    }



总结:模板引擎的整个过程:

  1、当浏览器请求index.php文件时,实例化模板类对像 $_tpl = new Templates();

  2、当Templates实例化的时候,生成两个数组,一个用来存放模板变量,另一个存放系统变量,通过构造方法,判断文件夹是否存在,同时通过XML文件将系统变量数组初始化

  3、通过模板类Templates的注入方法,assign(),将对应模板index.tpl中变量的index.php的内容注入到模板类的私有变量,完成初始化

  4、模板类Templates类显示方法display() 通过实例化解析类Parser,将取到的注入变量通过解析类进行解析(即替换)

  5、解析(替换)后,将文件写入PHP、HTML混全文件

  6、通过Templates类的显示方法将文件输出:

     1、第一次执行显示方法时,将会把PHP、HTML混合文件,生成纯静态的缓存文件

     2、调用缓存文件,显示页面

     3、当浏览器再次调用显示方法时,首先根据各文件的最后修改时间,判断是否重新生成缓存文件或直接调用已存在的缓存文件

重点:

  1、通过正则表达式进行字符串的替换

  2、熟悉OOP

1 0
原创粉丝点击