欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
一個(gè)簡(jiǎn)單的PHP模板引擎

PHP早期開(kāi)發(fā)中通常是PHP代碼和HTML代碼混寫(xiě),這也使代碼中充斥著(zhù)數據庫操作,邏輯處理等。當項目不大時(shí),這樣的代碼還可以接受,但是隨著(zhù)項目不斷擴大,我們就會(huì )發(fā)現同一個(gè)文件中同時(shí)存在前端邏輯和后端處理,當邏輯越來(lái)越復雜時(shí),代碼的可讀性和可維護性都會(huì )變得非常差,以至于后來(lái)不得不進(jìn)行大規模的代碼重構。所以后來(lái)就出現了代碼分層的思想,盡量拆分開(kāi)前端代碼和后端代碼。

PHP模板引擎能解決這種混亂嗎?當然可以。但是呢,即使你不用專(zhuān)門(mén)的模板引擎也可以寫(xiě)出邏輯清晰的代碼,重點(diǎn)是要有分層的思想,有專(zhuān)門(mén)的腳本去進(jìn)行數據獲取,數據處理,邏輯處理等,在展示頁(yè)面只進(jìn)行盡可能簡(jiǎn)單的邏輯處理即可。既然這樣,那還有使用PHP模板引擎的必要嗎?毫無(wú)疑問(wèn)當然有,因為模板引擎的功能不僅于此。

那接下來(lái)就說(shuō)一下PHP模板引擎的主要作用:

1、它實(shí)現了一些自定義標簽,用于展示層的簡(jiǎn)單邏輯處理,相較于不適用引擎的好處是代碼看起來(lái)不像是PHP代碼了,感覺(jué)上HTML代碼和PHP代碼完全分開(kāi)了,但這只是假象,壞處是效率降低了,因為這樣的頁(yè)面需要專(zhuān)門(mén)的腳本解析后才能正確顯示,解析的方法就是使用正則表達式替換,這明顯降低了效率。到現在來(lái)看感覺(jué)PHP模板引擎有還不如沒(méi)有呢,那為什么還要用它呢,重點(diǎn)是他的下一個(gè)功能。

2、文件緩存,這是模板引擎在生產(chǎn)環(huán)境中提高效率的非常好的手段??梢杂迷陧?yè)面加載時(shí)所用數據量很大但不經(jīng)常變或者不需要實(shí)時(shí)更新,即使延遲一會(huì )也無(wú)妨的頁(yè)面。我個(gè)人感覺(jué)文件緩存是PHP模板引擎的最重要的部分。

接下來(lái)我們就寫(xiě)一個(gè)簡(jiǎn)易的模板引擎(最后有完整文件代碼

首先我們先要計劃好我們的所需要的基礎類(lèi),有Template類(lèi)和Compile類(lèi)。

在我們具體實(shí)現編譯功能之前先搭好一個(gè)空的骨架,具體如下:

<?php/*** 模板引擎基礎類(lèi)*/class Template{ private $config = array( 'suffix' => '.m', // 設置模板文件的后綴 'templateDir' => 'template/', // 設置模板所在的文件夾 'compileDir' => 'cache/', // 設置編譯后存放的目錄 'cache_html' => true, // 是否需要編譯成靜態(tài)的HTML文件 'suffix_cache' => '.html', // 設置編譯文件的后綴 'cache_time' => 7200, // 多長(cháng)時(shí)間自動(dòng)更新,單位秒 'php_turn' => true, // 是否支持原生PHP代碼 'cache_control' => 'control.dat', 'debug' => false, ); private static $instance = null; private $value = array(); // 值棧 private $compileTool; // 編譯器 public $file; // 模板文件名,不帶路徑 public $debug = array(); // 調試信息 private $controlData = array(); public function __construct($config = array()) { $this->debug['begin'] = microtime(true); $this->config = $config + $this->config; if (! is_dir($this->config['templateDir'])) { exit('模板目錄不存在!'); } if (! is_dir($this->config['compileDir'])) { mkdir($this->config['compileDir'], 0770); } $this->getPath(); include './Compile.php'; } /** *獲取絕對路徑 */ public function getPath() { $this->config['templateDir'] = strtr(realpath($this->config['templateDir']), '\\', '/').'/'; $this->config['compileDir'] = strtr(realpath($this->config['compileDir']), '\\', '/').'/'; } /** *取得模板引擎的實(shí)例 */ public static function getInstance() { if (is_null(self::$instance)) { self::$instance = new self(); } return self::$instance; } /* 設置模板引擎參數 */ public function setConfig($key, $value = null) { if (is_array($key)) { $this->config = $key + $this->config; }else { $this->config[$key] = $value; } } /* 獲取當前模板引擎配置,僅供調試使用 */ public function getConfig($key = null) { if ($key) { return $this->config[$key]; }else { return $this->config; } } /** *注入單個(gè)變量 */ public function assign($key, $value) { $this->value[$key] = $value; } /** *注入數組變量 */ public function assignArray($array) { if (is_array($array)) { foreach($array as $k => $v) { $this->value[$k] = $v; } } } /** * 獲取模板文件完整路徑 */ public function path() { return $this->config['templateDir'].$this->file.$this->config['suffix']; } /** *判斷是否開(kāi)啟了緩存 */ public function needCache() { return $this->config['cache_html']; } /** *顯示模板 */ public function show($file) { }}?>

從上邊的代碼中我們能發(fā)現對于模板文件不存在和編譯文件不存在處理方式不同,這也很容易理解,如果你連模板文件都沒(méi)有有啥好編譯的,但是你有模板文件沒(méi)編譯文件這也很正常,正常進(jìn)行編譯即可。

如上所示,我們首先想好了這個(gè)模板引擎需要什么配置,還有一些設置配置的方法和檢查配置的方法等,而我們的核心方法show()還沒(méi)有實(shí)現呢,先不著(zhù)急,我們先去寫(xiě)編譯類(lèi)Compile,如下所示:

<?phpclass Compile{    private $template;   // 待編譯的文件    private $content;   // 需要替換的文件    private $comfile;   // 編譯后的文件    private $left = '{';   // 左定界符    private $right = '}';   // 右定界符    private $value = array();   // 值棧    private $phpTurn;    private $T_P = array();   // 匹配正則數組    private $T_R = array();   // 替換數組    public function __construct($template, $compileFile, $config) {        $this->template = $template;        $this->comfile = $compileFile;        $this->content = file_get_contents($template);    }    public function compile() {        $this->c_var();        file_put_contents($this->comfile, $this->content);    }    public function c_var() {        $this->content = preg_replace($this->T_P, $this->T_R, $this->content);    }    public function __set($name, $value) {        $this->$name = $value;    }    public function __get($name) {        return $this->$name;    }}?>

從上面Compile類(lèi)的構造函數我們可以看出,他需要模板文件路徑,編譯文件路徑,和具體編譯時(shí)的配置參數,但是在這這個(gè)配置參數嗎,沒(méi)有用到。之前說(shuō)過(guò)模板引擎主要使用的正則表達式來(lái)進(jìn)行匹配替換,將模板文件編譯成能正確執行的PHP文件,這里使用數組存放正則匹配數組和替換數組來(lái)進(jìn)行整體替換。

接下來(lái)我們就簡(jiǎn)單實(shí)現幾個(gè)常用的標簽,先看怎么替換簡(jiǎn)單變量:

// \x7f-\xff表示ASCII字符從127到255,其中\為轉義,作用是匹配漢字$this->T_P[] = '#\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}#';$this->T_R[] = '<?php echo \$this->value['\\1']; ?>';

正如我們看到的,上邊的那個(gè)是正則匹配,下邊的是替換。但是我們沒(méi)有給編譯類(lèi)的value變量賦值,那這個(gè)替換能找到正確的值嗎?答案是能,因為他用的不是這個(gè)類(lèi)的value用的是模板類(lèi)的value,接下來(lái)一會(huì )會(huì )講到。

然后我們在看看怎么實(shí)現foreach標簽,這個(gè)很常用

$this->T_P[] = '#\{(loop|foreach)\s+\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*\}#i';$this->T_P[] = '#\{\/(loop|foreach)\}#';
  $this->T_P[] = '#\{([k|v])\}#';
$this->T_R[] = '<?php foreach ((array)\$this->value['\\2'] as \$k => \$v) { ?>';$this->T_R[] = '<?php } ?>';
 $this->T_R[] = '<?php echo \$\\1?>';

這里用到的主要正則表達式的知識有:元組、反向引用等,這些只要稍微看一下正則表達式基礎就能理解了。

我們再來(lái)一個(gè)if else標簽:

$this->T_P[] = '#\{\/(loop|foreach|if)\}#';$this->T_P[] = '#\{if (.*?)\}#';$this->T_P[] = '#\{(else if|elseif) (.*?)\}#';$this->T_P[] = '#\{else\}#';$this->T_R[] = '<?php } ?>';$this->T_R[] = '<?php if(\\1){ ?>';$this->T_R[] = '<?php }elseif(\\2){ ?>';$this->T_R[] = '<?php }else{ ?>';

我們將if的閉合標簽和foreach的閉合標簽放一塊了。

現在我們已經(jīng)能編譯一些標簽了我們就再轉回模板類(lèi),現在我們想一想要怎么展示呢,這個(gè)才是我們的根本目的。寫(xiě)代碼之前先理一下思路:

1、判斷是否開(kāi)啟了緩存,如果是進(jìn)行第二步,否則直接進(jìn)行編譯輸出。

2、判斷是否需要更新緩存(判斷方式主要是緩存時(shí)間和編譯文件和模板文件的修改時(shí)間的關(guān)系),如果是就進(jìn)行第三步,否則直接讀取緩存文件輸出。

3、重新編譯模板文件,并將編譯后的PHP文件輸出保存到靜態(tài)緩存文件中。

簡(jiǎn)單來(lái)說(shuō)就是上邊的那三個(gè)步驟,具體實(shí)現如下:

/** *是否需要重新生成靜態(tài)文件 */ public function reCache($file) { $flag = true; $cacheFile = $this->config['compileDir'].md5($file).$this->config['suffix_cache']; if ($this->config['cache_html'] === true) { $timeFlag = (time() - @filemtime($cacheFile)) < $this->config['cache_time'] ? true : false; if (is_file($cacheFile) && filesize($cacheFile) > 1 && $timeFlag && filemtime($compileFile) >= filemtime($this->path())) { $flag = false; }else { $flag = true; } } return $flag; } /** *顯示模板 */ public function show($file) { $this->file = $file; if (! is_file($this->path())) { exit('找不到對應的模板!'); } $compileFile = $this->config['compileDir'].md5($file).'.php'; $cacheFile = $this->config['compileDir'].md5($file).$this->config['suffix_cache']; extract($this->value, EXTR_OVERWRITE); if ($this->config['cache_html'] === true) { if ($this->reCache($file) === true) { $this->debug['cached'] = 'false'; $this->compileTool = new Compile($this->path(), $compileFile, $this->config); if ($this->needCache()) {ob_start();} if (! is_file($compileFile) || filemtime($compileFile) < filemtime($this->path())) { $this->compileTool->value = $this->value; $this->compileTool->compile(); include $compileFile; }else { include $compileFile; } if ($this->needCache()) { $message = ob_get_contents(); file_put_contents($cacheFile, $message); } }else { readfile($cacheFile); $this->debug['cached'] = 'true'; } }else { if (! is_file($compileFile) || filemtime($compileFile) < filemtime($this->path())) { $this->compileTool = new Compile($this->path(), $compileFile, $this->config); $this->compileTool->value = $this->value; $this->compileTool->compile(); include $compileFile; }else { include $compileFile; } } $this->debug['spend'] = microtime(true) - $this->debug['begin']; $this->debug['count'] = count($this->value); }

上邊的代碼基本是按照上述的三個(gè)步驟來(lái)進(jìn)行的,好好看一下不難理解。

接下來(lái)就是模板文件了:

<html>{$data},{$person}<br/>列表一:<br/><ul>{foreach $arr1}<li>$v</li>{/foreach}</ul><br/>列表二:<br/><ul>{loop $arr2}<li>$v</li>{/loop}</ul>{if $a == '1'}a等于1{elseif $a == '2'}a等于2{else}a不等于1也不等于2{/if}</html>

這個(gè)模板文件主要測試了之前我們事先的模板標簽。

下面寫(xiě)一個(gè)測試文件:

<?phpinclude_once './Template.php';$tpl = new Template();$tpl->assign('data', 'hello');$tpl->assign('person', 'world!');$tpl->assign('arr1', array('123','456','789'));$tpl->assign('arr2', array('abc', 'def', 'ghi'));$tpl->assign('a', '2');$tpl->show('member');?>

這就是一個(gè)簡(jiǎn)單的測試我們的模板引擎能不能用的測試用例。

下面我們看看完整代碼吧:

<?php/*** 模板引擎基礎類(lèi)*/class Template{    private $config = array(        'suffix' => '.m',      // 設置模板文件的后綴        'templateDir' => 'template/',    // 設置模板所在的文件夾        'compileDir' => 'cache/',    // 設置編譯后存放的目錄        'cache_html' => true,    // 是否需要編譯成靜態(tài)的HTML文件        'suffix_cache' => '.html',    // 設置編譯文件的后綴        'cache_time' => 7200,    //  多長(cháng)時(shí)間自動(dòng)更新,單位秒        'php_turn' => true,   // 是否支持原生PHP代碼        'cache_control' => 'control.dat',        'debug' => false,    );    private static $instance = null;    private $value = array();   // 值棧    private $compileTool;   // 編譯器    public $file;     // 模板文件名,不帶路徑    public $debug = array();   // 調試信息    private $controlData = array();    public function __construct($config = array())    {        $this->debug['begin'] = microtime(true);        $this->config = $config + $this->config;        if (! is_dir($this->config['templateDir'])) {            exit('模板目錄不存在!');        }        if (! is_dir($this->config['compileDir'])) {            mkdir($this->config['compileDir'], 0770);        }        $this->getPath();        include './Compile.php';    }    /**    *獲取絕對路徑    */    public function getPath() {        $this->config['templateDir'] = strtr(realpath($this->config['templateDir']), '\\', '/').'/';        $this->config['compileDir'] = strtr(realpath($this->config['compileDir']), '\\', '/').'/';    }    /**    *取得模板引擎的實(shí)例    */    public static function getInstance() {        if (is_null(self::$instance)) {            self::$instance = new self();        }        return self::$instance;    }    /* 設置模板引擎參數 */    public function setConfig($key, $value = null) {        if (is_array($key)) {            $this->config = $key + $this->config;        }else {            $this->config[$key] = $value;        }    }    /* 獲取當前模板引擎配置,僅供調試使用 */    public function getConfig($key = null) {        if ($key) {            return $this->config[$key];        }else {            return $this->config;        }    }    /**    *注入單個(gè)變量    */    public function assign($key, $value) {        $this->value[$key] = $value;    }    /**    *注入數組變量    */    public function assignArray($array) {        if (is_array($array)) {            foreach($array as $k => $v) {                $this->value[$k] = $v;            }        }    }    /**     * 獲取模板文件完整路徑     */    public function path() {        return $this->config['templateDir'].$this->file.$this->config['suffix'];    }    /**    *判斷是否開(kāi)啟了緩存    */    public function needCache() {        return $this->config['cache_html'];    }    /**    *是否需要重新生成靜態(tài)文件    */    public function reCache($file) {        $flag = true;        $cacheFile = $this->config['compileDir'].md5($file).$this->config['suffix_cache'];        if ($this->config['cache_html'] === true) {            $timeFlag = (time() - @filemtime($cacheFile)) < $this->config['cache_time'] ? true : false;            if (is_file($cacheFile) && filesize($cacheFile) > 1 && $timeFlag && filemtime($compileFile) >= filemtime($this->path())) {                $flag = false;            }else {                $flag = true;            }        }        return $flag;    }    /**    *顯示模板    */    public function show($file) {        $this->file = $file;        if (! is_file($this->path())) {            exit('找不到對應的模板!');        }        $compileFile = $this->config['compileDir'].md5($file).'.php';        $cacheFile = $this->config['compileDir'].md5($file).$this->config['suffix_cache'];        extract($this->value, EXTR_OVERWRITE);        if ($this->config['cache_html'] === true) { // 開(kāi)啟緩存的處理邏輯            if ($this->reCache($file) === true) { // 需要更新緩存的處理邏輯                $this->debug['cached'] = 'false';                $this->compileTool = new Compile($this->path(), $compileFile, $this->config);                if ($this->needCache()) {ob_start();} // 打開(kāi)輸出控制緩沖                if (! is_file($compileFile) || filemtime($compileFile) < filemtime($this->path())) {                    $this->compileTool->value = $this->value;                    $this->compileTool->compile();                    include $compileFile;                }else {                    include $compileFile;                }                if ($this->needCache()) {                    $message = ob_get_contents(); // 獲取輸出緩沖中的內容(在include編譯文件的時(shí)候就有輸出了)                    file_put_contents($cacheFile, $message);                }            }else {                readfile($cacheFile);                $this->debug['cached'] = 'true';            }        }else {            if (! is_file($compileFile) || filemtime($compileFile) < filemtime($this->path())) {                $this->compileTool = new Compile($this->path(), $compileFile, $this->config);                $this->compileTool->value = $this->value;                $this->compileTool->compile();                include $compileFile;            }else {                include $compileFile;            }        }        $this->debug['spend'] = microtime(true) - $this->debug['begin'];        $this->debug['count'] = count($this->value);        //$this->debug_info();    }    public function debug_info() {        if ($this->config['debug'] === true) {            echo PHP_EOL, '---------debug info---------', PHP_EOL;            echo '程序運行日期:', date('Y-m-d H:i:s'), PHP_EOL;            echo '模板解析耗時(shí):', $this->debug['spend'], '秒', PHP_EOL;            echo '模板包含標簽數目:', $this->debug['count'], PHP_EOL;            echo '是否使用靜態(tài)緩存:', $this->debug['cached'], PHP_EOL;            echo '模板引擎實(shí)例參數:', var_dump($this->getConfig());        }    }    /**    *清理緩存的HTML文件    */    public function clean($path = null) {        if ($path === null) {            $path = $this->config['compileDir'];            $path = glob($path.'* '.$this->config['suffix_cache']);        }else {            $path = $this->config['compileDir'].md5($path).$this->config['suffix_cache'];        }        foreach((array)$path as $v) {            unlink($v);        }    }}?>
<?phpclass Compile{ private $template; // 待編譯的文件 private $content; // 需要替換的文件 private $comfile; // 編譯后的文件 private $left = '{'; // 左定界符 private $right = '}'; // 右定界符 private $value = array(); // 值棧 private $phpTurn; private $T_P = array(); // 匹配正則數組 private $T_R = array(); // 替換數組 public function __construct($template, $compileFile, $config) { $this->template = $template; $this->comfile = $compileFile; $this->content = file_get_contents($template); if ($config['php_turn'] === true) { $this->T_P[] = '#<\?(=|php|)(.+?)\?#is'; $this->T_R[] = '<?\1\2?>'; } // 變量匹配 // \x7f-\xff表示ASCII字符從127到255,其中\為轉義,作用是匹配漢字 $this->T_P[] = '#\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}#'; // foreach標簽盤(pán)匹配 $this->T_P[] = '#\{(loop|foreach)\s+\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*\}#i'; $this->T_P[] = '#\{\/(loop|foreach|if)\}#'; $this->T_P[] = '#\{([k|v])\}#'; // if else標簽匹配 $this->T_P[] = '#\{if (.*?)\}#'; $this->T_P[] = '#\{(else if|elseif) (.*?)\}#'; $this->T_P[] = '#\{else\}#'; $this->T_P[] = '#\{(\#|\*)(.*?)(\#|\*)\}#'; $this->T_R[] = '<?php echo \$this->value['\\1']; ?>'; $this->T_R[] = '<?php foreach ((array)\$this->value['\\2'] as \$k => \$v) { ?>'; $this->T_R[] = '<?php } ?>'; $this->T_R[] = '<?php echo \$\\1?>'; $this->T_R[] = '<?php if(\\1){ ?>'; $this->T_R[] = '<?php }elseif(\\2){ ?>'; $this->T_R[] = '<?php }else{ ?>'; $this->T_R[] = ''; } public function compile() { $this->c_var(); //$this->c_staticFile(); file_put_contents($this->comfile, $this->content); } public function c_var() { $this->content = preg_replace($this->T_P, $this->T_R, $this->content); } /* 對引入的靜態(tài)文件進(jìn)行解析,應對瀏覽器緩存 */ public function c_staticFile() { $this->content = preg_replace('#\{\!(.*?)\!\}#', '<script src=\1'.'?t='.time().'></script>', $this->content); } public function __set($name, $value) { $this->$name = $value; } public function __get($name) { return $this->$name; }}?>

模板文件member.m代碼:

<html>{$data},{$person}<br/>列表一:<br/><ul>{foreach $arr1}<li>$v</li>{/foreach}</ul><br/>列表二:<br/><ul>{loop $arr2}<li>$v</li>{/loop}</ul>{if $a == '1'}a等于1{elseif $a == '2'}a等于2{else}a不等于1也不等于2{/if}</html>

測試用例:

<?phpinclude_once './Template.php';$tpl = new Template();$tpl->assign('data', 'hello');$tpl->assign('person', 'world!');$tpl->assign('arr1', array('123','456','789'));$tpl->assign('arr2', array('abc', 'def', 'ghi'));$tpl->assign('a', '2');$tpl->show('member');?>

本文內容大部分來(lái)自于《PHP核心技術(shù)與最佳實(shí)踐》的第六章。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
PHP 實(shí)現簡(jiǎn)單的模板引擎
寫(xiě)自己的模板引擎
PHPliB類(lèi)詳解
ecshop模板制作1
開(kāi)發(fā)函數計算的正確姿勢 —— 使用 Fun Local 本地運行與調試
從ThinkPHP框架核心討論C、E、G、L、T、I、N...等函數
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久