亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

自定義php模板引擎

2020-03-22 17:31:06
字體:
來源:轉載
供稿:網友
  • 模板引擎的思想是來源于MVC(Model View Controller)模型,即模型層、視圖層、控制器層。

    在Web端,模型層為數據庫的操作;視圖層就是模板,也就是Web前端;Controller就是PHP對數據和請求的各種操作。模板引擎就是為了將視圖層和其他層分離開來,使php代碼和html代碼不會混雜在一起。因為當php代碼和html代碼混雜在一起時,將使代碼的可讀性變差,并且代碼后期的維護會變得很困難。

    大部分的模板引擎原理都差不多,核心就是利用正則表達式解析模板,將約定好的特定的標識語句編譯成php語句,然后調用時只需要include編譯后的文件,這樣就講php語句和html語句分離開來了。甚至可以更進一步將php的輸出輸出到緩沖區,然后將模板編譯成靜態的html文件,這樣請求時,就是直接打開靜態的html文件,請求速度大大加快。

    簡單的自定義模板引擎就是兩個類,第一個是模板類、第二個是編譯類。


    首先是編譯類:

    class CompileClass {    private $template;      // 待編譯文件    private $content;       // 需要替換的文本    private $compile_file;       // 編譯后的文件    private $left = '{';       // 左定界符    private $right = '}';      // 右定界符    private $include_file = array();        // 引入的文件    private $config;        // 模板的配置文件    private $T_P = array();     // 需要替換的表達式    private $T_R = array();     // 替換后的字符串        public function __construct($template, $compile_file, $config) {}        public function compile() {        $this->c_include();        $this->c_var();        $this->c_staticFile();        file_put_contents($this->compile_file, $this->content);    }        // 處理include    public function c_include() {}        // 處理各種賦值和基本語句    public function c_var() {}        // 對靜態的JavaScript進行解析        public function c_staticFile() {}}

    編譯類的大致結構就是上面那樣,編譯類的工作就是根據配置的文件,將寫好的模板文件按照規則解析,替換然后輸出到文件中。這個文件的內容是php和html混雜的,但在使用模板引擎進行開發時并不需要在意這個文件,因為我們要編寫的是模板文件,也就是html和我們自己定義的標簽混合的一個文件。這樣View和其他兩層就分離開來了。

    在這個自定義模板引擎中,我的左右定界符就是大括號,具體的解析規則就是放在__construct()中

    // 需要替換的正則表達式$this->T_P[] = "/$this->lefts*/$([a-zA-Z_-ÿ][a-zA-Z0-9_÷-ÿ]*)s*$this->right/";$this->T_P[] = "/$this->lefts*(loop|foreach)s*/$([a-zA-Z_-ÿ][a-zA-Z0-9_÷-ÿ]*)s*$this->right/";$this->T_P[] = "/$this->lefts*(loop|foreach)s*/$([a-zA-Z_-ÿ][a-zA-Z0-9_÷-ÿ]*)s+"        . "ass+/$([a-zA-Z_-ÿ][a-zA-Z0-9_÷-ÿ]*)$this->right/";$this->T_P[] = "/$this->lefts*/(loop|foreach|if)s*$this->right/";$this->T_P[] = "/$this->lefts*if(.*?)s*$this->right/";$this->T_P[] = "/$this->lefts*(else if|elseif)(.*?)s*$this->right/";$this->T_P[] = "/$this->lefts*elses*$this->right/";$this->T_P[] = "/$this->lefts*([a-zA-Z_-ÿ][a-zA-Z0-9_÷-ÿ]*)s*$this->right/";// 替換后的字符串         $this->T_R[] = "<?php echo $/1; ?>";$this->T_R[] = "<?php foreach((array)$/2 as $K=>$V) { ?>";$this->T_R[] = "<?php foreach((array)$/2 as &$/3) { ?>";$this->T_R[] = "<?php } ?>";$this->T_R[] = "<?php if(/1) { ?>";$this->T_R[] = "<?php } elseif(/2) { ?>";$this->T_R[] = "<?php } else { ?>";$this->T_R[] = "<?php echo $/1; ?>";

    上面的解析規則包含了基本的輸出和一些常用的語法,if、foreach等。利用preg_replace函數就能對模板文件進行替換。具體情況如下

    <!--模板文件-->{$data}{foreach $vars}    {if $V == 1 }        <input value="{V}">    {elseif $V == 2}        <input value="123123">    {else }        <input value="sdfsas是aa">    {/if}{/foreach}{ loop $vars as $var}    <input value="{var}">{ /loop }

    // 解析后<?php echo $data; ?><?php foreach((array)$vars as $K=>$V) { ?>    <?php if( $V == 1) { ?>        <input value="<?php echo $V; ?>">    <?php } elseif( $V == 2) { ?>        <input value="123123">    <?php } else { ?>        <input value="sdfsas是aa">    <?php } ?><?php } ?><?php foreach((array)$vars as &$var) { ?>    <input value="<?php echo $var; ?>"><?php } ?>

    編譯類的工作大致就是這樣,剩下的include和對JavaScript的解析都和這個大同小異。


    然后就是模板類

    class Template {    // 配置數組        private $_arrayConfig = array(        'root' => '',       // 文件根目錄        'suffix' => '.html',       // 模板文件后綴        'template_dir' => 'templates',      // 模板所在文件夾        'compile_dir' => 'templates_c',       // 編譯后存放的文件夾        'cache_dir' => 'cache',     // 靜態html存放地址        'cache_htm' => false,       // 是否編譯為靜態html文件        'suffix_cache' => '.htm',       // 設置編譯文件的后綴        'cache_time' => 7200,        // 自動更新間隔        'php_turn' => true,      // 是否支持原生php代碼        'debug' => 'false',    );    private $_value = array();          private $_compileTool;      // 編譯器    static private $_instance = null;          public $file;        // 模板文件名    public $debug = array();        // 調試信息        public function __construct($array_config=array()) {}        // 單步設置配置文件    public function setConfig($key, $value=null) {}        // 注入單個變量    public function assign($key, $value) {}        // 注入數組變量    public function assignArray($array) {}        // 是否開啟緩存    public function needCache() {}        // 如果需要重新編譯文件    public function reCache() {}        // 顯示模板    public function show($file) {}    }

    整個模板類的工作流程就是先實例化模板類對象,然后利用assign和assignArray方法給模板中的變量賦值,然后調用show方法,將模板和配置文件傳入編譯類的實例化對象中然后直接include編譯后的php、html混編文件,顯示輸出。簡單的流程就是這樣,詳細的代碼如下


    public function show($file) {    $this->file = $file;    if(!is_file($this->path())) {        exit("找不到對應的模板文件");    }    $compile_file = $this->_arrayConfig['compile_dir']. md5($file). '.php';    $cache_file = $this->_arrayConfig['cache_dir']. md5($file). $this->_arrayConfig['suffix_cache'];    // 如果需要重新編譯文件    if($this->reCache($file) === false) {        $this->_compileTool = new CompileClass($this->path(), $compile_file, $this->_arrayConfig);        if($this->needCache()) {            // 輸出到緩沖區            ob_start();        }        // 將賦值的變量導入當前符號表        extract($this->_value, EXTR_OVERWRITE);        if(!is_file($compile_file) or filemtime($compile_file) < filemtime($this->path())) {            $this->_compileTool->vars = $this->_value;            $this->_compileTool->compile();            include($compile_file);        }        else {            include($compile_file);        }        // 如果需要編譯成靜態文件        if($this->needCache() === true) {            $message = ob_get_contents();            file_put_contents($cache_file, $message);        }    }    else {        readfile($cache_file);    }}


    在show方法中,我首先判斷模板文件存在,然后利用MD5編碼生成編譯文件和緩存文件的文件名。然后就是判斷是否需要進行編譯,判斷的依據是看編譯文件是否存在和編譯文件的寫入時間是否小于模板文件。如果需要編譯,就利用編譯類進行編譯,生成一個php文件。然后只需要include這個編譯文件就好了。

    為了加快模板的載入,可以將編譯后的文件輸出到緩沖區中,也就是ob_start()這個函數,所有的輸出將不會輸出到瀏覽器,而是輸出到默認的緩沖區,在利用ob_get_contents()將輸出讀取出來,保存成靜態的html文件。

    具體的使用如下

    require('Template.php');$config = array(    'debug' => true,    'cache_htm' => false,    'debug' => true);$tpl = new Template($config);$tpl->assign('data', microtime(true));$tpl->assign('vars', array(1,2,3));$tpl->assign('title', "hhhh");$tpl->show('test');

    緩存后的文件如下

    <!DOCTYPE html><html>    <head>        <title>hhhh</title>        <meta charset="UTF-8">        <meta name="viewport" content="width=device-width, initial-scale=1.0">    </head>    <body>        1466525760.32                                    <input value="1">                                                <input value="123123">                                                <input value="sdfsas是aa">                                                <input value="1">                    <input value="2">                    <input value="3">                <script src="123?t=1465898652"></script>    </body></html>

    一個簡單的自定義模板引擎就完成了,雖然簡陋但是能用,而且重點在于造輪子的樂趣和收獲。

    完整代碼可見我的 github

    歡迎訪問我的個人博客:www.czrzchao.com

    PHP編程

    鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

  • 發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
    欧美精品激情在线观看| 日韩精品小视频| 日日骚av一区| 久久视频在线观看免费| 久久综合五月天| 久久天天躁夜夜躁狠狠躁2022| 国产成人亚洲综合青青| 精品中文字幕乱| 精品久久久久久亚洲国产300| 欧洲美女7788成人免费视频| 中文字幕精品视频| 国产精品丝袜白浆摸在线| 日韩不卡中文字幕| 欧美激情精品久久久久久大尺度| 欧美日韩综合视频网址| 国产欧亚日韩视频| 欧美情侣性视频| 国产91在线高潮白浆在线观看| 欧美中文在线观看| 亚洲精品资源美女情侣酒店| 欧美成人在线免费| 国产精品美女主播| 欧美老女人在线视频| 亚洲午夜激情免费视频| 97在线精品视频| 久久国产精品首页| 欧美日韩免费观看中文| 欧美黄色片在线观看| 亚洲韩国欧洲国产日产av| 成人免费网站在线| 欧美激情视频在线免费观看 欧美视频免费一| 国产精品中文在线| 九九热这里只有精品免费看| 国产噜噜噜噜噜久久久久久久久| 国产精品国产福利国产秒拍| 久久影视三级福利片| 日韩精品中文字幕视频在线| 亚洲伊人成综合成人网| 亚洲三级av在线| 丝袜亚洲另类欧美重口| 欧美日韩一二三四五区| 亚洲在线视频观看| 亚洲欧美中文另类| 国产欧美日韩视频| 97视频在线观看亚洲| 7777免费精品视频| 成人福利免费观看| 亚洲精品一区二区三区婷婷月| 亚洲精品美女在线观看| 欧美性生交xxxxxdddd| 欧美成人激情图片网| 一区二区三区国产视频| 国产91精品网站| 北条麻妃在线一区二区| 国产一区二区三区在线免费观看| 97视频人免费观看| 亚洲精品乱码久久久久久按摩观| 欧美日韩在线视频一区| 欧美激情网站在线观看| 狠狠躁夜夜躁人人爽超碰91| 亚洲欧洲在线视频| 国产精品九九久久久久久久| 亚洲激情视频在线观看| 欧美与欧洲交xxxx免费观看| 欧美色视频日本高清在线观看| 亚洲天堂av在线播放| 一区二区三区视频免费在线观看| 久久亚洲国产精品成人av秋霞| 97视频在线观看视频免费视频| 欧美成人精品不卡视频在线观看| 96精品视频在线| 另类少妇人与禽zozz0性伦| 亚洲已满18点击进入在线看片| 91色视频在线导航| 国产成人精品免费视频| 亚洲视频在线免费观看| 欧美丰满少妇xxxxx| 国产极品jizzhd欧美| 富二代精品短视频| 国产91精品视频在线观看| 欧美在线视频一二三| 少妇高潮久久77777| 91精品国产91久久久久久吃药| 性欧美xxxx视频在线观看| 久久久久久久久久av| 在线中文字幕日韩| 中文字幕一区电影| 欧美亚洲视频在线观看| 欧美精品在线网站| 亚洲理论片在线观看| 久久亚洲国产精品| 性视频1819p久久| 91免费人成网站在线观看18| 国产欧美精品久久久| 久久精视频免费在线久久完整在线看| 亚洲电影av在线| 色综合天天综合网国产成人网| 亚洲国产精品高清久久久| 6080yy精品一区二区三区| 欧美高清videos高潮hd| 午夜精品久久久久久久白皮肤| 亚洲福利在线看| 亚洲国产中文字幕在线观看| 伊人精品在线观看| 国产精品免费观看在线| 色综合色综合久久综合频道88| 日韩久久午夜影院| 欧美激情一级二级| 日本精品va在线观看| 97在线观看视频国产| 国产精品久久久久99| 91伊人影院在线播放| 色婷婷av一区二区三区久久| 成人精品网站在线观看| 亚洲精品动漫久久久久| 国产精品欧美日韩一区二区| 日韩视频在线免费| 亚洲九九九在线观看| 国产一区二区三区直播精品电影| 国产一区二区三区在线观看视频| 97国产在线视频| 日韩美女视频在线观看| 久久99久久亚洲国产| 欧美限制级电影在线观看| 一区二区三区黄色| 成人黄色免费网站在线观看| 久久免费视频观看| 亚洲美女视频网| 欧美尤物巨大精品爽| 亚洲精品日韩丝袜精品| 亚洲欧洲在线免费| 欧美日韩亚洲一区二区| 亚洲女人天堂成人av在线| 亚洲欧美国产精品专区久久| 国产精品成人观看视频国产奇米| 国产亚洲欧美日韩一区二区| 亚洲男人7777| 国产精品美乳一区二区免费| 亚洲欧美中文在线视频| 91精品视频观看| 国产一区二区三区视频在线观看| 亚洲精品久久久久国产| 精品综合久久久久久97| 国产精品pans私拍| 久久精品久久久久久国产 免费| 亚洲一区二区三区777| 欧美一级片久久久久久久| 亚洲亚裔videos黑人hd| 91美女福利视频高清| 欧美成人黄色小视频| 综合久久五月天| 日本久久亚洲电影| 色yeye香蕉凹凸一区二区av| 国内精品视频久久| 日韩中文字幕网址| 伊人精品在线观看| 亚洲午夜精品视频| 国产成人精品视频在线观看| 4438全国成人免费| 久久国内精品一国内精品| 人人做人人澡人人爽欧美| 亚洲va男人天堂| 国产经典一区二区| 久久成人免费视频|