簡介:這是phpcms 源碼解析-------模板引擎的詳細頁面,介紹了和php,phpcms, php phpcms 源碼解析-------模板引擎有關的知識、技巧、經驗,和一些php源碼等。
class='pingjiaF' frameborder='0' src='http://biancheng.dnbcw.info/pingjia.php?id=357338' scrolling='no'>
PHPCMS 整站程式碼分析講解(六)之模板引擎
發布:水水
19 May
<?php
/**
函數 template函數是在global.func.php 裡面定義的。 在前面的phpcms 的首頁 index.php 裡就見到了。 用法: include template() 用法很熟, 呵呵其實和 dz 的模板引擎一樣的用法。 但DZ的模板引擎比 PHPCMS 的簡單很多,因為沒有用到模板的標籤技術。 大家有空可以研究下DZ的模板引擎。這裡不說。 好分析下上面這個 模板的主要函數吧。 他的作用是返回編譯好的模板檔案路徑。也就是把模板 X.html(模板檔案) 用正則替換成 x.php(編譯後的PHP檔案).然後使用 include 函數。懂了吧! php的模板引擎都一個鳥樣。 然後剩下的就是正則的東西了。等下再說。
*/
function template($module = 'phpcms', $template = 'index')
{
global $CONFIG;
$compiledtplfile = $CONFIG['templatescachedir'].$module.'_'.$template.'.tpl.php';
/**
因為phpcms是分模組來存放模板檔案。所以 template 函數有兩個參數: 第一個就是模組目錄名,第二個就是此模組裡面的模板檔案名稱.
$CONFIG['templatescachedir'] 這個是放編譯後php檔案存放的目錄。在config.inc.php 網站設定檔裡面定義的自己去看。 這樣就取得了模板編譯後的php檔案路徑。
*/
if($CONFIG['templaterefresh']) //$CONFIG['templaterefresh'] 在 config.inc.php裡面配置了。預設是1 。是更新模板開關。如果你設定為0 那麼模板更新了。程式也不會更新。
{
$tplfile = PHPCMS_ROOT.'/templates/'.$CONFIG['defaulttemplate'].'/'.$module.'/'.$template.'.html';
/**
和上面那句意思差不多。$CONFIG['defaulttemplate'] 是預設範本目錄 。這句是擷取你要的那個模組和裡面的那個模板檔案的路徑(@@擷取沒編譯前的模板檔案)
*/
if(!file_exists($compiledtplfile) || @filemtime($tplfile) > @filemtime($compiledtplfile))
{
/**
我把檔案編譯成了php檔案。那麼模板改變了。 php檔案總得也改變吧。要不你修改了模板後。站還是以前那個樣子沒變那有什麼意思呢。
首先判斷模板編譯檔案是否存在。如果不存在那麼後邊那個條件不用判斷了。 因為編譯檔案都不存在。程式肯定運行不了拉。(因為其實我們主要是運行編譯後的那個php檔案,模板檔案是html的運行個P呀)
或 後邊那個 @filemtime($tplfile) > @filemtime($compiledtplfile) 很容易就明白: 函數 filetime() 判斷檔案最近修改的時間,返回Unix 時間戳記。 如果模板檔案的修改時間 大於 編譯檔案。 那麼證明 模板檔案 在 編譯檔案產生後 還進行了修改。那麼我們是不是還要在更新次編譯檔案呀 ,那是肯定的拉。 所以繼續執行下去。
*/
require_once PHPCMS_ROOT.'/include/template.func.php'; // 載入編譯函數
template_refresh($tplfile, $compiledtplfile);// 這個就是模板的 編譯啟動函數 ,帶動一系列的模板編譯函數來最終產生模板編譯檔案。
}
}
return $compiledtplfile; // 返回 模板編譯後的PHP檔案路徑。
}
defined('IN_PHPCMS') or exit('Access Denied');
function template_compile($module,$template) //和下面那個一樣是編譯模板啟動函數。不過兩函數的參數不一樣,按照上下文意思。這個函數是為了配合批量編譯模板而寫的。第一個是模組目錄名,第二是模板檔案名稱,解釋同下。請看下面那個
{
global $CONFIG;
$content = file_get_contents(PHPCMS_ROOT.'/templates/'.$CONFIG['defaulttemplate'].'/'.$module.'/'.$template.'.html');
$content = template_parse($content);
$compiledtplfile = $CONFIG['templatescachedir'].$module.'_'.$template.'.tpl.php';
$strlen = file_put_contents($compiledtplfile, $content);
@chmod($compiledtplfile, 0777);
return $strlen;
}
function template_refresh($tplfile,$compiledtplfile) //模板編譯啟動函數。 參數 第一個是 模板檔案名稱 第二個是 編譯後的php檔案名稱
{
$str = file_get_contents($tplfile); //使用了php5 的最爽函數:file_get_contents() 擷取檔案的內容 。
$str = template_parse($str); /*然後 使用 template_parse() 函數來對檔案內容進行替換。比如把一些我們自己定義的語句:{if xx > xx} 正則替換成 <?php if(xx > xx){?>具體看下面*/
$strlen = file_put_contents($compiledtplfile, $str);//編譯完成後。把內容寫到我們的 那個所謂的編譯PHP檔案。
@chmod($compiledtplfile, 0777); //別忘了設定下許可權。
return $strlen; //返回 寫到編譯檔案裡的內容字大小節數,下面我們看下 template_parse() 函數
}
function template_module($module)//這個很有用。批量編譯某模組目錄下的模板檔案
{
global $CONFIG;
$files = glob(PHPCMS_ROOT.'/templates/'.$CONFIG['defaulttemplate'].'/'.$module.'/*.html');
/*
glob 函數 取得 在此路徑下的所有 *.html 以html為副檔名的檔案清單。 具體看手冊。
**/
if(is_array($files))
{
foreach($files as $tpl)
{ //開始批量
$template = str_replace('.html', '', basename($tpl));
// 擷取模板檔案名稱。以次來做編譯後的PHP檔案名稱
template_compile($module, $template); //這個函數上面講過了。看上面
}
}
return TRUE;
}
function template_cache() //這個是比上面那個更大批量的產生。因為 $MODULE 裡面的所有模組 $MODULE 存在於快取檔案模板。前面已經說了。自己看吧
{
global $MODULE;
foreach($MODULE as $module=>$m)
{
template_module($module);
}
return TRUE;
}
/**
哇,別給它嚇到。其實都是些簡單的正則。只要知道他們是幹什麼的就好辦了。 在模板裡面我們使用了些自己定義的標籤呀。語句呀。這些東西不是PHP標準文法。所以根本不可能運行。
那麼怎麼辦呢。通過正則對我們自己定義的文法 。轉變成標準的PHP文法。然後寫到我們的 PHP檔案裡。所以下面正則都是對我們自己定義的文法進行編譯。
下面講解下正則。按照本人水平解釋。大概的解釋了下。不過不懂正則的請自己百度學下。有不對的地方。大家可以討論下。@@ 還沒懂 preg_replace() 函數的同學兄弟朋友姐妹。請自己看手冊。
*/
function template_parse($str)
{
$str = preg_replace("/([\n\r]+)\t+/s","\\1",$str);
// 用 \n\r 過濾掉 tab定位字元, \\1 是逆向引用了第一個括弧裡面\n換行\r換頁匹配的文本 (@@解釋好要口,最好自己看下正則知識 /s為修正符。自己百度吧)
$str = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}",$str);
// 以 {xx} 來替換 <!--{xx}--> {xx}在下面肯定還要進行第二次正則替換,要不是不能在PHP裡面啟動並執行。 .+? 和 .+ 一個是懶惰 一個是貪婪。 看名字就知道。不知道的 百度吧: 正則貪婪。
$str = preg_replace("/\{template\s+(.+)\}/","\n<?php include template(\\1); ?>\n",$str);
/* 把模板裡面的 {template 'xx','jj'} 編譯成PHP標準寫法:<?php include template('xx','jj') ?> 大家可能一看就明白了: include template() 這個在那裡見過。對了。這個在PHP裡也可以啟動並執行。因為 template() 函數不是定義了嗎。*/
$str = preg_replace("/\{include\s+(.+)\}/","\n<?php include \\1; ?>\n",$str);
/* 模板裡面的 {include xx.php} 編譯成 PHP檔案裡的 <?php include xx.php?>**/
$str = preg_replace("/\{php\s+(.+)\}/","\n<?php \\1?>\n",$str);
/* 模板裡面的 {php xxxx} 編譯成 <?php xxxx?> 大家也應該明白了。 xxxx 肯定是PHP的標準文法拉。 所以phpcms模板語句: {php } 就是用來給你在模板裡寫要啟動並執行PHP語句。在smarty 裡也有這功能**/
$str = preg_replace("/\{if\s+(.+?)\}/","<?php if(\\1) { ?>",$str);
/* 這個就更簡單了。 把模板裡面的{if xxxx} 編譯成 <?php if(){?> 看這樣一步一步的把一些自己定義的語句編譯成PHP的標準文法。這個就叫模板引擎了。**/
$str = preg_replace("/\{else\}/","<?php } else { ?>",$str);
/* {else } 轉 <?php } else {?>**/
$str = preg_replace("/\{elseif\s+(.+?)\}/","<?php } elseif (\\1) { ?>",$str);
/* {elseif } 轉 <?php } elseif {?>**/
$str = preg_replace("/\{\/if\}/","<?php } ?>",$str);
/* {/if} 轉 <?php }?> phpcms 模板文法有: {/if}的哦。大家別忘了,要不 php肯定運行不了**/
$str = preg_replace("/\{loop\s+(\S+)\s+(\S+)\}/","<?php if(is_array(\\1)) foreach(\\1 AS \\2) { ?>",$str);
/* 下面就是迴圈了。模板裡用{loop xx jj} 其實編譯成了PHP的 foreach(xx AS jj) 這樣大家都會用了吧**/
$str = preg_replace("/\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}/","\n<?php if(is_array(\\1)) foreach(\\1 AS \\2 => \\3) { ?>",$str);
/* 這句和上面也差不多。不過是多了個取出數組的標名 {loop xx jj yy} 成 foreach(xx as jj=> yy)**/
$str = preg_replace("/\{\/loop\}/","\n<?php } ?>\n",$str);
/* 迴圈結束別忘了 {/loop} 對應PHP的 <?php }?>**/
$str = preg_replace("/\{tag_([^}]+)\}/e", "get_tag('\\1')", $str);
/* {tag_xx} 替換為 get_tag('xx') get_tag() 函數是自己定義的函數,因為phpcms 的模板引擎應用了標籤功能。這個函數就是為了調用標籤的。**/
$str = preg_replace("/\{([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\(([^{}]*)\))\}/","<?php echo \\1;?>",$str);
/* {xxx(jj)} 這麼個奇怪的東西。因為奇怪所以我找了下PHPCMS的模板檔案。找了幾個檔案都沒發現這個怪物。大家有誰找到的說下我去看下。怕是我理解錯了正則。先謝了**/
$str = preg_replace("/\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\(([^{}]*)\))\}/","<?php echo \\1;?>",$str);
/* {$xxx(wwsd)} 專換成 <?php echo xxx(wwsd)?> 當然了 xxx() 是程式中定義過的函數**/
$str = preg_replace("/\{([a-zA-Z0-9_\x7f-\xff]*)\}/]\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/","<?php echo \\1;?>",$str);
/* 把{$xxjj} 轉成 <?php echo $xxjj?> 當然了是把變數輸出**/
$str = preg_replace("/\{(\]\\$[a-zA-Z0-9_\[\]\'\"\$\x7f-\xff]+)\}/es", "addquote('<?php echo \\1;?>')",$str);
/* 主要是把{$xxx['jj']} 轉成 <?php echo $xxx['jj']?> addquote() 函數自己定義的看下面,二次過濾。有代驗證,頭昏了看太久的黃色字。我昏**/
$str = preg_replace("/\{([A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*)\}/s", "<?php echo \\1;?>",$str);
/* {XXJJ} <?php echo XXJJ?> XXJJ 是我們定義的常量**/
$str = "<?php defined('IN_PHPCMS') or exit('Access Denied'); ?>".$str;
/* 最後別忘了在自己的每個編譯後的檔案裡加上這個。以前講過了不明白找前面例子**/
return $str; //最後返回過濾完成的內容
}
function get_tag($tagname) //這個函數在 上面這個編譯函數裡面看到了。 其實就是擷取對應標籤的內容,頭有點昏,下節再說標籤吧。
{
global $tags,$html,$CONFIG;
if(!$tags) require PHPCMS_ROOT.'/templates/'.$CONFIG['defaulttemplate'].'/tags.php';
if(!$html) require PHPCMS_ROOT.'/templates/'.$CONFIG['defaulttemplate'].'/html.php';
if(!isset($tags[$tagname])) return '{tag_'.$tagname.'}';
$code = isset($html[$tagname]) ? 'tag_read('.$html[$tagname].')' : $tags[$tagname];
return "<?php echo $code;?>";
}
function addquote($var)
{
return str_replace("[url=]\\\[/url]"", """, preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
}
?>
[size=xx-small][/size]
愛J2EE關注Java邁克爾傑克遜視頻站JSON線上工具
http://biancheng.dnbcw.info/php/357338.html pageNo:2