PHP--關於模板的原理與解析
此内容用作笔记,以备日后查看,此内容为学习李炎恢课程而来,并非自己所创,如有问题请私信~
将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
<span>php //index.php</span>
//设置编码为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';
<span></span><span>$_name</span> = '方块李'<span>; </span><span>$array</span> = <span>array</span>(1,2,3,4,5,6<span>); </span><span>$_tpl</span> = <span>new</span><span> Templates(); </span><span>$_tpl</span>->assign('name', <span>$_name</span><span>); </span><span>$_tpl</span>->assign('a', 5>4<span>); </span><span>$_tpl</span>->assign('array', <span>$array</span><span>); </span><span>//</span><span>显示</span><span>$_tpl</span>->display('index.tpl'<span>); </span>?>
模板文件 HTML
<meta http-equiv="Content-Type" c> <title><!--{webname}--></title> {<strong>include</strong> "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}
模板类:
//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>"; <strong>include</strong> $_cacheFile; return; } } } //判断编译文件是否存在,模板文件是否修改过 if(!file_exists($_parFile) || (filemtime($_parFile) require ROOT_PATH.'/<strong>include</strong>s/Parser.class.php'; //实例化<strong>对象</strong>,生成编译文件 $_parser = new Parser($_tplFile);//模板文件 $_parser->compile($_parFile);//编译后文件 } //载入编译文件 <strong>include</strong> $_parFile; if(IS_CACHE){ //生成缓存文件 file_put_contents($_cacheFile, ob_get_contents()); //清除缓冲区 ob_end_clean(); //载入缓存文件 <strong>include</strong> $_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语句没有关闭'); } } } //解析<strong>include</strong> private function par<strong>include</strong>(){ $_pattern = '/\{<strong>include</strong>\s+\"(.*)\"\}/'; if(preg_match($_pattern, $this->_tpl,$_file)){ //判断头文件是否存在 if(!file_exists($_file[1]) || empty($_file[1])){ exit('ERROR:包含文件不存在!'); } //替换内容 $this->_tpl = preg_replace($_pattern, "<?php <strong>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(); //解析<strong>include</strong> $this->par<strong>include</strong>(); //解析系统变量 $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
以上就介绍了PHP--關於模板的原理與解析,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。
