thinkPHP3.0框架实现模板保存到数据库的方法
author:一佰互联 2019-04-25   click:141

本文实例讲述了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_EXIST_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->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->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->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 && $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.".class.php")) {
            $tpl  = new $class;
            $tpl->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->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) > 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) > filemtime($tmplCacheFile)) {
        return false;
      }
    }
    // 缓存有效
    return true;
  }
}

5.添加自己解析模板内容的类TemplateEy.class.php(这个放在thinkphpExtendDriverTemplate目录下面)
只是将系统默认的ThinkTemplate.class.php类修改了fetch方法修改代码如下:

// 加载模板
public function fetch($templateFile,$templateContent,$templateVar) {
    $this->tVar = $templateVar;
    if($templateContent && !$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->fetch("Ext:New:Frontend:show",$params["tpl"][$display_mode]);
}else{
return $this->fetch("Ext:New:Frontend:show");
}

更多关于thinkPHP相关内容感兴趣的读者可查看本站专题:《ThinkPHP入门教程》、《thinkPHP模板操作技巧总结》、《ThinkPHP常用方法总结》、《codeigniter入门教程》、《CI(CodeIgniter)框架进阶教程》、《Zend FrameWork框架入门教程》及《PHP模板技术总结》。

希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。