PHP 小巧简单带静态缓存的模版类
时间:2013-05-03
来源:互联网
class Template
{
public $caching = false; //模版缓存开关 true | false
private $_config = array(
'path' => 'template', //模版文件路径
'compile_path' => 'template_compile', //模版编译文件路径
'suffix' => '.html', //模版后缀
'cache_path' => 'cache', //缓存路径
'cache_name' => '' //缓存名称
);
private $_templateName;
private $_templateVars;
private static $_instance;
private function __construct(){}
public static function getInstance()
{
if (empty(self::$_instance)) {
self::$_instance = new self;
}
return self::$_instance;
}
public function setConfig($config)
{
if (!empty($config)) {
$config = array_merge($this->_config, $config);
}
$this->_config = array_change_key_case($config);
return $this;
}
/*
* 模版变量赋值
* @param mixed 变量名称 支持批量设置,如: array('title' => '', 'name' => '');
* @param mixed 变量值 如果为批量设置方式则无效
*/
public function assign($vars, $value = '')
{
if (is_array($vars)) {
foreach ($vars as $key => $val) {
if (!empty($key)) $this->_templateVars[$key] = $val;
}
} else {
if (!empty($vars)) $this->_templateVars[$vars] = $value;
}
}
private function _templatePath($templateName)
{
return $this->_config['path'].'/'.$templateName.$this->_config['suffix'];
}
private function _compilePath($templateName)
{
return $this->_config['compile_path'].'/'.$templateName.'.compile';
}
//使用__var__这样的命名尽量避免污染模版变量
public function fetch($__templateName__)
{
$this->_compile($__templateName__);
if (!empty($this->_templateVars)) extract($this->_templateVars);
ob_start();
$__file__ = $this->_compilePath($__templateName__);
if (is_file($__file__)) {
include $this->_compilePath($__templateName__);
$content = ob_get_clean();
return $content;
} else {
throw new Exception(__METHOD__.'找不到模板编译文件: '.$__file__);
}
}
private function _compile($templateName)
{
$templateFile = $this->_templatePath($templateName);
$compileFile = $this->_compilePath($templateName);
if (!is_file($compileFile) || @filemtime($templateFile) > @filemtime($compileFile)) {
if (is_file($templateFile)) {
$content = file_get_contents($templateFile);
$content = self::_parse($content);
self::_makeDir(dirname($compileFile));
file_put_contents($compileFile, $content);
} else {
echo '模板文件不存在: '.$templateFile;
throw new Exception(__METHOD__.'找不到模板文件: '.$templateFile);
}
}
}
private static function _parse($content)
{
//过滤模板<!-- -->注释
$content = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $content);
//模板包含模板
$content = preg_replace("/\{template\sfile=(\"?)([\w|-]+)\\1\}/i", "<?php echo \$this->fetch('\\2'); ?>", $content);
//PHP标签
$content = preg_replace("/\{php\s+(.+)\}/", "<?php \\1?>", $content);
//echo变量
$content = preg_replace("/\{(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/", "<?php echo \\1;?>", $content);
//echo常量
$content = preg_replace("/\{([A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*)\}/s", "<?php echo \\1;?>", $content);
//echo函数
$content = preg_replace("/\{([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff:]*\(([^{}]*)\))\}/","<?php echo \\1;?>", $content);
//if
$content = preg_replace("/\{if\s+(.+?)\}/", "<?php if(\\1) { ?>", $content);
//else
$content = preg_replace("/\{else\}/", "<?php } else { ?>", $content);
//elseif
$content = preg_replace("/\{elseif\s+(.+?)\}/", "<?php } elseif (\\1) { ?>", $content);
//end if
$content = preg_replace("/\{\/if\}/", "<?php } ?>", $content);
//foreach
$content = preg_replace("/\{loop\s+(\S+)\s+(\S+)\}/", "<?php if(is_array(\\1)) foreach(\\1 AS \\2) { ?>", $content);
$content = preg_replace("/\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}/","<?php if(is_array(\\1)) foreach(\\1 AS \\2 => \\3) { ?>", $content);
$content = preg_replace("/\{\/loop\}/", "<?php } ?>", $content);
//echo foreach 变量
$content = preg_replace("/\{(\\$[a-zA-Z0-9_\[\]\'\"\$\x7f-\xff]+)\}/es", "self::_quote('<?php echo \\1;?>')", $content);
return $content;
}
private static function _quote($var)
{
return str_replace("\\\"", "\"", preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
}
/*
* 模版输出
* @param string 如果之前有缓存isCache(template)判断,可留空
*/
public function display($templateName = '')
{
if (!empty($this->_templateName)) $templateName = $this->_templateName;
if ($this->caching == true) {
$templateFile = $this->_templatePath($templateName);
$cacheFile = $this->_getCacheFile();
if (!$this->_checkCache($templateFile, $cacheFile)) {
$content = $this->fetch($templateName);
self::_makeDir(dirname($cacheFile));
file_put_contents($cacheFile, $content);
} else {
$content = file_get_contents($cacheFile);
}
echo $content;
} else {
echo $this->fetch($templateName);
}
}
private function _getCacheFile()
{
if (!$this->_config['cache_name']) $this->_config['cache_name'] = $this->_templateName;
return $this->_config['cache_path'].'/'.$this->_config['cache_name'].'.html';
}
private static function _checkCache($templateFile, $cacheFile)
{
if (!is_file($cacheFile) || @filemtime($templateFile) > @filemtime($cacheFile)) {
return false;
}
return true;
}
public function isCache($templateName)
{
$this->_templateName = $templateName;
if ($this->caching == false) return false;
$templateFile = $this->_templatePath($templateName);
$cacheFile = $this->_getCacheFile();
if (!$this->_checkCache($templateFile, $cacheFile)) return false;
return true;
}
/*
* 清除模版HTML缓存文件
* @param string 参数同glob 默认为当前模版
* [url=http://bbs.phpchina.com/home.php?mod=space&uid=987628]@Return[/url] bool
*/
public function clearCache($search = '')
{
if (!empty($search)) {
$files = glob($this->_config['cache_path'].'/'.$search.'.html');
if (!empty($files)) {
foreach ($files as $file) {
if (is_file($file)) unlink($file);
}
return true;
}
}
return is_file($this->_getCacheFile()) ? unlink($this->_getCacheFile()) : false;
}
private static function _makeDir($dir, $mode = 0777)
{
if (!is_dir($dir)) {
self::_makeDir(dirname($dir), $mode);
return mkdir($dir, $mode);
}
return true;
}
}
$Tpl = Template::getInstance();
$Tpl->setConfig(array('path' => 'tpl'));
$Tpl->setConfig(array('compile_path' => 'tpl_c'));
$Tpl->setConfig(array('cache_path' => 'tpl_cache'));
//常规赋值
$Tpl->assign('author', '作者');
//批量赋值
$Tpl->assign(array('title' => '标题', 'content' => '内容'));
//使用try来捕获类可能存在的错误
try{
//开启缓存(永久缓存)
$Tpl->caching = true; // *注意 caching 必须开启,下面的缓存才有效
$page = 1; //这里表示分页$_GET['page']
//设置缓存文件名
$Tpl->setConfig(array('cache_name' => 'index-'.$page)); //根据分页来缓存
//检查缓存是否存在
if (!$Tpl->isCache('index')) { //这里的index为模版名,下面的display就不用再传递
echo '写缓存...并且一系列的操作……';
}
$Tpl->display();
} catch (Exception $e) {
echo '<p>'.$e->getMessage().'</p>';
}
//清除缓存
//比如在后台操作
//后台可能模板类被重新实例化 (配置前台缓存的目录)
$Tpl->setConfig(array('cache_path' => 'tpl_cache'));
//参数同php glob()函数
$Tpl->clearCache('index-1'); //清除index-1缓存文件
$Tpl->clearCache('index-*'); //清除index-为前缀的缓存文件
模版语法:http://www.yytweb.com/a/41.html
作者: gyyst 发布时间: 2013-05-03
看着写那么一大堆assign,就相当不爽,浪费太多时间在没有意义的assign上了。远不如php include来得方便
作者: xuer 发布时间: 2013-05-04
xuer 发表于 2013-5-4 23:04
看着写那么一大堆assign,就相当不爽,浪费太多时间在没有意义的assign上了。远不如php include来得方便 ...
看着写那么一大堆assign,就相当不爽,浪费太多时间在没有意义的assign上了。远不如php include来得方便 ...
. 受打击了
作者: gyyst 发布时间: 2013-05-05
嗯还可以简化一下额 呵呵
作者: Frank_Luo 发布时间: 2013-05-14
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28















