天天看點

thinkPHP3.0架構實作模闆儲存到資料庫的方法

本文執行個體講述了thinkPHP3.0架構實作模闆儲存到資料庫的方法。分享給大家供大家參考,具體如下:

在開發cms的時候用到如果将模闆檔案存入到資料庫并顯示到頁面中

由于thinkphp3.0都是直接從模闆檔案中讀取再解析的那麼對于模闆存入資料庫中就隻有自己開發了,還有thinkphp3.0中有mode的功能我們可以定義自己的mode這樣就可以達到目的了,那麼如何來擴充自己的mode呢?如下:

1.在你的入口檔案中輸入

define('MODE_NAME','Ey');

其中"Ey"就是你自己擴充的mode名稱了,請在你的thinkphp/Extend/Mode檔案下面建立Ey檔案夾

2.在Ey目錄中修改

添加tags.php檔案内容如下:

return array(

'app_init'=>array(

),

'app_begin'=>array(

'ReadHtmlCache', // 讀取靜态緩存

),

'route_check'=>array(

'CheckRoute', // 路由檢測

),

'app_end'=>array(),

'path_info'=>array(),

'action_begin'=>array(),

'action_end'=>array(),

'view_begin'=>array(),

'view_template'=>array(

'ExtensionTemplate', // 自動定位模闆檔案(手動添加)

),

'view_content'=>array(

'ParseContent'//(手動添加)

),

'view_filter'=>array(

'ContentReplace', // 模闆輸出替換

'TokenBuild', // 表單令牌

'WriteHtmlCache', // 寫入靜态緩存

'ShowRuntime', // 運作時間顯示

),

'view_end'=>array(

'ShowPageTrace', // 頁面Trace顯示

),

);

該檔案中後面的注釋中添加手動添加了為我的修改,隻是修改thinkphp中預設的tags中查找模闆和解析模闆的行為

将系統預設的action和view類複制到Ey的目錄中(由于解析内容,是以要修改action和view類),修改action.class.php中的fetch方法:

protected function fetch($templateFile='',$templateContent='' ){

return $this->view->fetch($templateFile,$templateContent);

}

view.class.php檔案中的修改為:

public function fetch($templateFile='',$templateContent = NULL) {

$params['templateFile'] = $templateFile;

$params['cacheFlag'] = true;

if(isset($templateContent)) {

$params['templateContent'] = $templateContent;

}

tag('view_template',$params);

// 頁面緩存

ob_start();

ob_implicit_flush(0);

if('php' == strtolower(C('TMPL_ENGINE_TYPE'))) { // 使用PHP原生模闆

// 模闆陣列變量分解成為獨立變量

extract($this->tVar, EXTR_OVERWRITE);

// 直接載入PHP模闆

include $templateFile;

}else{

// 視圖解析标簽

$params = array('var'=>$this->tVar,'content'=>$params['templateContent'],'file'=>$params['templateFile'],'cacheFlag'=>$params['cacheFlag']);

tag('view_content',$params);

}

// 擷取并清空緩存

$content = ob_get_clean();

// 内容過濾标簽

tag('view_filter',$content);

// 輸出模闆檔案

return $content;

}

3.擴充自己的查找模闆的類(自己擴充的行為tp讓我們放在thinkphpExtendBehavior中)

在thinkphpExtendBehavior中添加ExtensionTemplateBehavior.class.php類,内容如下:

class ExtensionTemplateBehavior extends Behavior {

// 行為擴充的執行入口必須是run

public function run(&$params){

if( is_array($params) ){

if( array_key_exists('templateFile', $params) ){

$params = $this->parseTemplateFile($params);

}else{

//異常

throw_exception(L('_TEMPLATE_NOT_E/【參考文章的時候,并不建議直接複制,應該盡量地讀懂】/XIST_AND_CONTENT_NULL_').'['.$params['templateFile'].']');

}

}else{

// 自動定位模闆檔案

if(!file_exists_case($params))

$params = $this->parseTemplateFile($params);

}

}

private function parseTemplateFile($params) {

if( is_array($params) ) {

$templateFile = $params['templateFile'];

}else{

$templateFile = $params;

}

if(!isset($params['templateContent'])) { // 是否設定 templateContent 參數

//自動擷取模闆檔案

if('' == $templateFile){

// 如果模闆檔案名為空 按照預設規則定位

$templateFile = C('TEMPLATE_NAME');

} elseif(false === strpos($templateFile,C('TMPL_TEMPLATE_SUFFIX'))) {

$path = explode(':',$templateFile);

//如果是插件

if($path[0] == 'Ext') {

$templateFile = str_replace(array('Ext:',$path[1] . ':',$path[2] . ':'),'',$templateFile);

$templateFile = SITE_ROOT . '/Ext/extensions/' . strtolower($path[1]) . '/' . $path[2] . '/Tpl/' . $templateFile . C('TMPL_TEMPLATE_SUFFIX');

} else {

// 解析規則為 模闆主題:子產品:操作 不支援 跨項目和跨分組調用

$action = array_pop($path);

$module = !empty($path)?array_pop($path):MODULE_NAME;

if(!empty($path)) {// 設定模闆主題

$path = dirname(THEME_PATH).'/'.array_pop($path).'/';

}else{

$path = THEME_PATH;

}

$depr = defined('GROUP_NAME')?C('TMPL_FILE_DEPR'):'/';

$templateFile = $path.$module.$depr.$action.C('TMPL_TEMPLATE_SUFFIX');

}

}

} else {

if('' == $templateFile){

$depr = defined('GROUP_NAME')?C('TMPL_FILE_DEPR'):'/';

$params['cacheFlag'] = false;

} else {

$path = explode(':',$templateFile);

//如果是插件

if($path[0] == 'Ext') {

$templateFile = str_replace(array('Ext:',$path[1] . ':',$path[2] . ':'),'',$templateFile);

$templateFile = SITE_ROOT . '/Ext/extensions/' . strtolower($path[1]) . '/' . $path[2] . '/Tpl/' . $templateFile . C('TMPL_TEMPLATE_SUFFIX');

} else {

// 解析規則為 模闆主題:子產品:操作 不支援 跨項目和跨分組調用

$action = array_pop($path);

$module = !empty($path)?array_pop($path):MODULE_NAME;

if(!empty($path)) {// 設定模闆主題

$path = dirname(THEME_PATH).'/'.array_pop($path).'/';

}else{

$path = THEME_PATH;

}

$depr = defined('GROUP_NAME')?C('TMPL_FILE_DEPR'):'/';

$templateFile = $path.$module.$depr.$action.C('TMPL_TEMPLATE_SUFFIX');

}

}

}

if( is_array($params) ){

$params['templateFile'] = $templateFile;

return $params;

}else{

if(!file_exists_case($templateFile))

throw_exception(L('_TEMPLATE_NOT_EXIST_').'['.$templateFile.']');

return $templateFile;

}

}

}

4.添加解析自己的模闆的行為類(這個和thinkphp3.0預設的ParseTemplateBehavior.class.php類似)

class ParseContentBehavior extends Behavior {

protected $options = array(

// 布局設定

'TMPL_ENGINE_TYPE' => 'Ey', // 預設模闆引擎 以下設定僅對使用Ey模闆引擎有效

'TMPL_CACHFILE_SUFFIX' => '.php', // 預設模闆緩存字尾

'TMPL_DENY_FUNC_LIST' => 'echo,exit', // 模闆引擎禁用函數

'TMPL_DENY_PHP' =>false, // 預設模闆引擎是否禁用PHP原生代碼

'TMPL_L_DELIM' => '{', // 模闆引擎普通标簽開始标記

'TMPL_R_DELIM' => '}', // 模闆引擎普通标簽結束标記

'TMPL_VAR_IDENTIFY' => 'array', // 模闆變量識别。留白自動判斷,參數為'obj'則表示對象

'TMPL_STRIP_SPACE' => true, // 是否去除模闆檔案裡面的html空格與換行

'TMPL_CACHE_ON' => true, // 是否開啟模闆編譯緩存,設為false則每次都會重新編譯

'TMPL_CACHE_TIME' => 0, // 模闆緩存有效期 0 為永久,(以數字為值,機關:秒)

'TMPL_LAYOUT_ITEM' => '{__CONTENT__}', // 布局模闆的内容替換辨別

'LAYOUT_ON' => false, // 是否啟用布局

'LAYOUT_NAME' => 'layout', // 目前布局名稱 預設為layout

// Think模闆引擎标簽庫相關設定

'TAGLIB_BEGIN' => '<', // 标簽庫标簽開始标記

'TAGLIB_END' => '>', // 标簽庫标簽結束标記

'TAGLIB_LOAD' => true, // 是否使用内置标簽庫之外的其它标簽庫,預設自動檢測

'TAGLIB_BUILD_IN' => 'cx', // 内置标簽庫名稱(标簽使用不必指定标簽庫名稱),以逗号分隔 注意解析順序

'TAGLIB_PRE_LOAD' => '', // 需要額外加載的标簽庫(須指定标簽庫名稱),多個以逗号分隔

);

public function run(&$_data){

$engine = strtolower(C('TMPL_ENGINE_TYPE'));

//這個地方要判斷是否存在檔案

if('think'==$engine){

if($this-&gt;checkCache($_data['file'])) { // 緩存有效

// 分解變量并載入模闆緩存

extract($_data['var'], EXTR_OVERWRITE);

//載入模版緩存檔案

include C('CACHE_PATH').md5($_data['file']).C('TMPL_CACHFILE_SUFFIX');

}else{

$tpl = Think::instance('ThinkTemplate');

// 編譯并加載模闆檔案

$tpl-&gt;fetch($_data['file'],$_data['var']);

}

} else if('ey' == $engine) {

if( !$_data['cacheFlag'] ){

$class = 'Template'.ucwords($engine);

if(is_file(CORE_PATH.'Driver/Template/'.$class.'.class.php')) {

// 内置驅動

$path = CORE_PATH;

} else {

// 擴充驅動

$path = EXTEND_PATH;

}

if(require_cache($path.'Driver/Template/'.$class.'.class.php')) {

$tpl = new $class;

$tpl-&gt;fetch('',$_data['content'],$_data['var']);

} else { // 類沒有定義

throw_exception(L('_NOT_SUPPERT_').': ' . $class);

}

}else{

//操作

$cache_flag = true;

if(isset($_data['content'])){ //如果指定内容

if ($_data['file']){ //指定緩存KEY

$_data['file'] = 'custom_' . $_data['file'];

} else { //未指定緩存KEY,則不緩存

$cache_flag = false;

}

} else {

if (is_file($_data['file'])){ //如果指定檔案存在

$_data['content'] = file_get_contents($_data['file']);

} else {

throw_exception(L('_TEMPLATE_NOT_EXIST_').'['.$_data['file'].']');

}

}

//這裡檔案和内容一定有一個存在,否則在之前就會有異常了

if($cache_flag &amp;&amp; $this->checkCache($_data['file'],$_data['content']) ) { // 緩存有效

// 分解變量并載入模闆緩存

extract($_data['var'], EXTR_OVERWRITE);

//載入模版緩存檔案

include C('CACHE_PATH').md5($_data['file']).C('TMPL_CACHFILE_SUFFIX');

} else {

$class = 'Template'.ucwords($engine);

if(is_file(CORE_PATH.'Driver/Template/'.$class.'.class.php')) {

// 内置驅動

$path = CORE_PATH;

} else {

// 擴充驅動

$path = EXTEND_PATH;

}

if(require_cache($path.'Driver/Template/'.$class.'/【本文中一些PHP版本可能是以前的,如果不是一定要,建議PHP盡量使用7.2以上的版本】/.class.php')) {

$tpl = new $class;

$tpl-&gt;fetch($_data['file'],$_data['content'],$_data['var']);

} else { // 類沒有定義

throw_exception(L('_NOT_SUPPERT_').': ' . $class);

}

}

}

} else {

//調用第三方模闆引擎解析和輸出

$class = 'Template'.ucwords($engine);

if(is_file(CORE_PATH.'Driver/Template/'.$class.'.class.php')) {

// 内置驅動

$path = CORE_PATH;

}else{ // 擴充驅動

$path = EXTEND_PATH;

}

if(require_cache($path.'Driver/Template/'.$class.'.class.php')) {

$tpl = new $class;

$tpl-&gt;fetch($_data['file'],$_data['var']);

}else { // 類沒有定義

throw_exception(L('_NOT_SUPPERT_').': ' . $class);

}

}

}

protected function checkCache($tmplTemplateFile = '',$tmplTemplateContent='') {

if (!C('TMPL_CACHE_ON'))// 優先對配置設定檢測

return false;

//緩存檔案名

$tmplCacheFile = C('CACHE_PATH').md5($tmplTemplateFile).C('TMPL_CACHFILE_SUFFIX');

if(!is_file($tmplCacheFile)){

return false;

}elseif (filemtime($tmplTemplateFile) &gt; filemtime($tmplCacheFile)) {

// 模闆檔案如果有更新則緩存需要更新

return false;

}elseif (C('TMPL_CACHE_TIME') != 0 && time() > filemtime($tmplCacheFile)+C('TMPL_CACHE_TIME')) {

// 緩存是否在有效期

return false;

}

// 開啟布局模闆

if(C('LAYOUT_ON')) {

$layoutFile = THEME_PATH.C('LAYOUT_NAME').C('TMPL_TEMPLATE_SUFFIX');

if(filemtime($layoutFile) &gt; filemtime($tmplCacheFile)) {

return false;

}

}

// 緩存有效

return true;

}

}

5.添加自己解析模闆内容的類TemplateEy.class.php(這個放在thinkphpExtendDriverTemplate目錄下面)

隻是将系統預設的ThinkTemplate.class.php類修改了fetch方法修改代碼如下:

// 加載模闆

public function fetch($templateFile,$templateContent,$templateVar) {

$this-&gt;tVar = $templateVar;

if($templateContent &amp;&amp; !$templateFile) { //不緩存

if(C('LAYOUT_ON')) {

if(false !== strpos($templateContent,'{__NOLAYOUT__}')) { // 可以單獨定義不使用布局

$templateContent = str_replace('{__NOLAYOUT__}','',$templateContent);

}else{ // 替換布局的主體内容

$layoutFile = THEME_PATH.C('LAYOUT_NAME').$this->config['template_suffix'];

$templateContent = str_replace($this->config['layout_item'],$templateContent,file_get_contents($layoutFile));

}

}

//編譯模闆内容

$templateContent = $this->compiler($templateContent);

extract($templateVar, EXTR_OVERWRITE);

echo $templateContent;

} else {

$templateCacheFile = $this->loadTemplate($templateFile,$templateContent);

// 模闆陣列變量分解成為獨立變量

extract($templateVar, EXTR_OVERWRITE);

//載入模版緩存檔案

include $templateCacheFile;

}

}

6.調用如果資料庫中模闆的内容不存在那麼我們還是去讀資料庫中的内容:

if( array_key_exists( $display_mode, $params['tpl'] ) && strlen($params['tpl'][$display_mode]) > 0 ){

return $this-&gt;fetch("Ext:New:Frontend:show",$params'tpl');

}else{

return $this->fetch("Ext:New:Frontend:show");

}