核心文件:DolrViews.class.php:
-
- /**
- * DolrPHP模板引擎
- * @author Joychao
- * @version 1.0 beta
- * @license
- */
- defined('DOLRVIEWS') or define('DOLRVIEWS',true);
- defined('DIR_SEP') or define('DIR_SEP',DIRECTORY_SEPARATOR);
- class DolrViews
- {
- /**
- * 单例对象
- *
- * @static var
- * @var object DolrViews
- */
- protected static $_instance;
- /**
- * 模板变量
- *
- * @var array
- */
- protected $_tpl_vars=array();
- /**
- * 模板参数信息
- *
- * @var array
- */
- protected $_options=array(
- 'template_dir'=>'templates',
- 'compile_dir'=>'templates_c',
- 'cache_dir'=>'cache',
- 'caching'=>false,
- 'cache_lifetime'=>3600,
- 'plugins_dir'=>'plugins',
- 'tpl_suffix'=>'html',
- 'php_handing'=>false,
- );
- /**
- * 包含的插件
- * @var array
- */
- protected $includePlugins=array();
- /**
- * 主模板非包含模板
- * @var string
- */
- protected $mainTplFileName;
- /**
- * 单件模式调用方法
- *
- * @static
- * @return object DolrViews
- */
- public static function getInstance($options=array()) {
- if (!self :: $_instance instanceof self)
- self :: $_instance = new self($options);
- return self :: $_instance;
- }
- /**
- * 构造函数,初始化所有配置
- *
- * @param array $config=array(); 配置数组
- * @example:
- * $_options=array(
-
* 'template_dir'=>'templates',
-
* 'compile_dir'=>'templates_c',
- * 'cache_dir'=>'cache',
- * 'caching'=>false,
- * 'cache_lifetime'=>3600,
- * 'plugins_dir'=>'plugins',
- * 'php_handing'=>false,
- * );
- * $tpl=new DolrViews($_options);
- */
- public function __construct($options=array())
- {
- if (!empty($options))
- {
- $this->setOptions($options);
- }
- }
- /**
- * 分配变量到模板
- *
- * @param string $varName 变量名
- * @param mixed $varValue 变量值
- */
- public function assign($varName,$varValue)
- {
- $this->_tpl_vars[$varName]=&$varValue;
- }
- /**
- * 显示输出到页面
- *
- * @param string $tplFileName 模板文件名
- */
- public function display($tplFileName,$cacheId=null)
- {
- $cacheId=is_null($cacheId)?$_SERVER['REQUEST_URI']:$cacheId;
- $this->mainTplFileName=$tplFileName;
- $tplFilePath=$this->_getTplPath($tplFileName);
- extract($this->_tpl_vars);
- //内置变量
- extract($this->_getSystemVars($tplFileName));//系统变量
- //是否缓存
- if($this->_options['caching']){
- if($this->isCached($tplFileName,$cacheId)){
- include
$this->_getCacheFile($tplFileName,$cacheId);
- }else{//否则缓存文件
- include
$this->_writeCache($tplFileName,$this->_parseTpl($tplFileName,$cacheId),$cacheId);//
写入缓存
- }
- }else{//非缓存模式
- include
$this->_parseTpl($tplFileName,$cacheId);//解析写入编译文件并包含
- }
- }
- /**
- * 配置模板选项
- *
- * @param array $options 配置数组
- */
- public function setOptions($options)
- {
- foreach ($options as $optionName => $optionValue) {
- $this->set($optionName,$optionValue);
- }
- }
- /**
- * 设置选项
- *
- * @param string $optionName 选项名称
- * @param mixed $optionValue 选项值
- */
- public function __set($optionName,$optionValue)
- {
- $this->set($optionName,$optionValue);
- }
- /**
- * 单独设置配置
- *
- * @param string $optionName 选项名称
- * @param mixed $optionValue 选项值
- */
- public function set($optionName,$optionValue)
- {
- switch (strtolower($optionName)) {
- case 'template_dir':
- $optionValue=$this->_trimPath($optionValue).DIR_SEP;
- if(!file_exists($optionValue))
- $this->_throwException('未找到指定的模板目录"'.$optionValue.'"');
- $this->_options['template_dir']=$optionValue;
- break;
- case 'compile_dir':
- $optionValue=$this->_trimPath($optionValue).DIR_SEP;
- if(!file_exists($optionValue))
- $this->_throwException('未找到指定的编译目录"'.$optionValue.'"');
- $this->_options['compile_dir']=$optionValue;
- break;
- case 'cache_dir':
- $optionValue=$this->_trimPath($optionValue).DIR_SEP;
- if(!file_exists($optionValue))
- $this->_throwException('未找到指定的缓存目录"'.$optionValue.'"');
- $this->_options['cache_dir']=$optionValue;
- break;
- case 'plugins_dir':
- $optionValue=$this->_trimPath($optionValue).DIR_SEP;
- if(!file_exists($optionValue))
- $this->_throwException('未找到指定的缓存目录"'.$optionValue.'"');
- $this->_options['plugins_dir']=$optionValue;
- break;
- case 'caching':
- $this->_options['caching']=(boolean)$optionValue;
- break;
- case 'cache_lifetime':
- $this->_options['cache_lifetime']=(float)$optionValue;
- break;
- case 'php_handing':
- $this->_options['php_handing']=(boolean)$optionValue;
- break;
- case 'tpl_suffix':
- $this->_options['tpl_suffix']=trim($optionValue);
- break;
- default:
- $this -> _throwException("未知的模板配置选项
\"$optionName\"");
- }
- }
- /**
- * 清除模板缓存
- *
- * @param string $tplFileName='' 模板文件名,不传入则删除所有缓存
- * @return boolean 成功或者失败
- */
- public function clearCache($tplFileName='',$cacheId=null)
- {
- $cacheId=is_null($cacheId)?$_SERVER['REQUEST_URI']:$cacheId;
- if(!empty($tplFileName)){
- $cacheFile=$this->_getCacheFile($tplFileName,$cacheId);
- if(file_exists($cacheFile)){
- chmod($cacheFile, 0777);
- @unlink($cacheFile);
- }
- }else{//删除所有缓存文件
- foreach (glob($this->_options['cache_dir'].'*')
as $cacheFile) {
- chmod($cacheFile, 0777);
- @unlink($cacheFile);
- }
- }
- }
- /**
- * 检测是否缓存了指定模板文件
- *
- * @param string $tplFileName 模板文件名
- * @return boolean
- */
- public function isCached( $tplFileName,$cacheId=null)
- {
- $tplFilePath=$this->_getTplPath($tplFileName);
- $cacheId=is_null($cacheId)?$_SERVER['REQUEST_URI']:$cacheId;
- $cacheFile=$this->_getCacheFile($tplFileName,$cacheId);
- if(file_exists($cacheFile) //存在
- and
filemtime($cacheFile)+$this->_options['cache_lifetime']>time()//未过期
- and filemtime($cacheFile)>filemtime($tplFilePath)
//模板没有改动
- ){//存在并没过期
- return true;
- }else{
- return false;
- }
- }
- /**
- * 获取内置变量
- * @return array
- */
- protected function _getSystemVars($tplFileName){
- //内置变量
- $_sysVars=array();
- $_sysVars['dolr_now']=time();
- $_sysVars['dolr_get']=$_GET;
- $_sysVars['dolr_post']=$_POST;
- $_sysVars['dolr_request']=$_REQUEST;
- $_sysVars['dolr_cookie']=isset($_COOKIE)?$_COOKIE:null;
- $_sysVars['dolr_session']=isset($_SESSION)?$_SESSION:null;
- $_sysVars['dolr_template']=basename($tplFileName);
- $const=get_defined_constants(true);
- $_sysVars['dolr_const']=$const['user'];
- $_sysVars['dolr_url']="http://".$_SERVER
['HTTP_HOST'].$_SERVER['PHP_SELF'];
- if(!empty($_SERVER['QUERY_STRING'])){
- $_sysVars['dolr_url'].='?'.$_SERVER['QUERY_STRING'];
- }
- return $_sysVars;
- }
- /**
- * 获取模板文件路径
- *
- * @param string $tplFileName 模板文件
- * @return string 文件名
- */
- protected function _getTplPath($tplFileName)
- {
- return
$this->_options['template_dir'].$this->_trimPath($tplFileName);
- }
- /**
- * 获取缓存的文件
- * @param string $tplFileName 模板文件
- * @return string 文件名
- */
- protected function _getCacheFile($tplFileName, $cacheId)
- {
- return
$this->_options['cache_dir'].$tplFileName.'.cache.'.md5($cacheId).'.php';
- }
- /**
- * 获取编译的文件名
- *
- * @param string $tplFileName 模板文件
- * @return string 文件名
- */
- protected function _getCompileFile( $tplFileName, $cacheId)
- {
- return
$this->_options['compile_dir'].$tplFileName.'.compile.php';
- }
- /**
- * 解析模板
- *
- * @param string $tplFileName 模板文件
- * @return string 解析后的内容
- */
- protected function _parseTpl($tplFileName,$cacheId)
- {
- $tplFilePath=$this->_getTplPath($tplFileName);
- if (!file_exists($tplFilePath) or
!is_readable($tplFilePath)) {
- $this->_throwException('不能打开指定的模板文件"'.$tplFileName.'"');
- }
- $content=file_get_contents($tplFilePath);
- //检测包含,检测所有的include 'xxx.html'
- preg_match_all('/[\n\r\t]*<\s*include\s+[\'"]\s*(.*?)\s*[\'"]\s*>[\n\r\t]*/s',
$content, $matches);
-
- if(!empty($matches[1])){
- foreach ($matches[1] as $key=>$fileName) {
- $includeFilePath=$this->_getTplPath($fileName);
- if (!file_exists($includeFilePath) or
!is_readable($includeFilePath)) {
- $this->_throwException('不能打开指定的模板文件"'.$includeFilePath.'"');
- }
- $includeCompilePath=$this->_getCompileFile($fileName,$cacheId);//得到编译文件名
- $this->_parseTpl($fileName,$cacheId);
- $content=str_replace($matches[0][$key],
'', $content);
- }
- }
- //规则
- $pattern=array(
- '/ \?\>[\n\r]*\<\? /s',//删除 PHP
代码断间多余的空格及换行
- '/(<\s*(\$[^>]+)\s*>)/es',//直接输出变量内容
- '/<\s*include\s+[\'"]\s*(.*?)\s*[\'"]\s*>/s',//包含模板
- '/<\s*if\s+(.+?)>(.+?)<\/if>/ies',//if
/if
- '/<\s*elseif\s+(.+?)>/ies',//elseif
- '/<\s*else\s*>/is',//else
- '/<\s*loop\s+(\S+)\s+(\S+)>(.+?)(.+?)<\/loop>/ies',//loop
$array $v
- '/<\s*loop\s+(\S+)\s+(\S+)>(.+?)<\/loop>/ies',//loop
$array $v
- '/<\s*loop\s+(\S+)\s+(\S+)\s+(\S+)>(.+?)(.+?)<\/loop>/ies',//loop
$array $k $v loopelse
- '/<\s*loop\s+(\S+)\s+(\S+)\s+(\S+)>(.+?)<\/loop>/ies',//loop
$array $k $v
- '/<\s*cycle\s+\'(\S+)\'\s*,\s*\'(\S+)\'>/',//
- );
- //PHP格式
- $php=array(
- ' ',
- "\$this->_parseVar('\\1')",
- '_options['template_dir']."\\1';?>",
- "\$this->_stripvtags('','\\2');",
- "\$this->_stripvtags('','');",
- '',
- "\$this->_stripvtags('','\\3\\4');",
- "\$this->_stripvtags('','\\3\n');",
- "\$this->_stripvtags(' \\3) {
?>','\\4\\5');",
- "\$this->_stripvtags(' \\3) {
?>','\\4');",
- "",
- );
- $content=preg_replace($pattern, $php, $content);
- //包含插件
- $pluginsString='';
- if($tplFileName==$this->mainTplFileName){//如果为主模板则放入include文件
- foreach ($this->includePlugins as $plugin) {
- $pluginsString.="include
\$this->_options['plugins_dir'].'{$plugin}';\n";
- }
- }
- $header=<<
-
- /**
- * {$tplFileName}
- * DolrViews 模板编译文件
- * @package {$this->mainTplFileName}
- */
- defined('DOLRVIEWS') or exit('Access denied');
- $pluginsString
- ?>\n
- DOLRVIEWS;
- $content=$header.$content;
- $compileFilePath=$this->_writeCompile($tplFileName,$content,$cacheId);//写入编译文件
- return $compileFilePath;
- }
- /**
- * 缓存模板文件
- *
- * @param string $tplFileName 模板文件
- * @param string $cacheId 缓存ID
- */
- protected function _writeCache($tplFileName,$cacheId)
- {
- $tplFilePath=$this->_getTplPath($tplFileName);
- $cacheFilePath=$this->_getCacheFile($tplFileName,$cacheId);//保存文件名
- $compileFilePath=$this->_getCompileFile($tplFileName,$cacheId);
- ini_set('error_reporting','off');//不缓存错误提示
- extract($this->_tpl_vars);//模板变量
- extract($this->_getSystemVars($tplFileName));//系统变量
- ob_start();
- if(file_exists($compileFilePath) and
filemtime($compileFilePath)>filemtime($tplFilePath))//模板没有改动
- {
- include $compileFilePath;
- }else{
- include
$this->_parseTpl($tplFileName,$cacheId);//解析并写入编译文件
- }
- $html=ob_get_contents();
- ob_clean();
- file_put_contents($cacheFilePath, $html);
- return $cacheFilePath;
- }
- /**
- * 写入编译文件
- *
- * @param string $tplFileName 模板文件
- * @param string $cacheId 缓存ID
- * @param string $content 网页
- */
- protected function
_writeCompile($tplFileName,$content,$cacheId)
- {
- $compileFilePath=$this->_getCompileFile($tplFileName,$cacheId);//保存文件名
- if(!file_exists(dirname($compileFilePath))){
- $this->_makeDir(dirname($compileFilePath));
- }
- file_put_contents($compileFilePath,$content);
- return $compileFilePath;
- }
- /**
- * 将路径修正为适合操作系统的形式
- *
- * @param string $path 路径名称
- * @return string
- */
- protected function _trimPath( $path)
- {
- return rtrim(str_replace(array('/', '\\', '//',
'\\\\'),DIR_SEP, $path),DIR_SEP);
- }
- /**
- * 根据指定的路径创建不存在的文件夹
- *
- * @param string $path 路径/文件夹名称
- * @return string
- */
- protected function _makeDir( $path)
- {
- $dirs = explode(DIR_SEP, $this ->_trimPath($path));
- $tmp = '';
- foreach ($dirs as $dir)
- {
- $tmp .= $dir . DIR_SEP;
- if (!file_exists($tmp) && !@mkdir($tmp,
0777))
- return $tmp;
- }
- return true;
- }
- /**
- * 变量处理
- *
- * @param string $string 目标字符串
- * @return string
- */
- protected function _parseVar($string){
- $pattern=array(
- '/^',
- '/>$/',
- '/(\$\w+\|[^>\s]+)/e',//$title|striptags|html2text
- '/(\$[\w]+\.[\w]+)/e',
- );
- $replacement=array(
- "
- ' ?>',
- "\$this->_parseModifier('\\1');",
- "\$this->_parsePoint('\\1');",
- );
- return stripslashes(preg_replace($pattern, $replacement,
$string));
- }
- /**
- * 变量调节器的处理
- *
- * @param string $string 模板中匹配到的变量
- * @return string 处理后的字符串
- */
- protected function _parseModifier($string)
- {
- $arr=explode('|', trim($string,';'));
- $tmp=array_shift($arr);
- foreach($arr as $value)
- {
- $tmpArr=explode(':',$value);//html2text
- $funcName=array_shift($tmpArr);//html2text
- $args=count($tmpArr)>0?','.join(',',$tmpArr):'';//参数用,号链接
arg1,arg2,arg3
- if(!function_exists($funcName)){//如果不是PHP内置函数则包含插件
- if(!file_exists($this->_options['plugins_dir'].'modifier_'.$funcName.'.php')){
- $this->_throwException('插件"'.$funcName.'"不存在');
- }
- $pluginFileName='modifier_'.$funcName.'.php';
- if(!in_array($pluginFileName,
$this->includePlugins)){
- $this->includePlugins[]=$pluginFileName;//添加include插件
- }
- $tmp="dolr_modifier_{$funcName}($tmp{$args})";
- }else{
- $tmp="{$funcName}($tmp{$args})";
- }
- }
- return stripslashes($tmp.';');
- }
- /**
- * 数组操作的点支持
- *
- * @param string $string 目标字符串
- * @return string
- */
- protected function _parsePoint($string)
- {
- $arr=explode('.',$string);//$a.b.c.f
- $varName=array_shift($arr);//$a
- return
$varName.'[\''.join('\'][\'',$arr).'\']';//$a['b']['c']['f']
- }
- /**
- * 去掉自定义标签
- *
- * @param string $expr 源文
- * @param string $statement 替换目标
- * @return string
- */
- protected function _stripvtags($expr, $statement)
- {
- $expr = str_replace("\\\"", "\"", preg_replace("/\<\?php echo
\\\$.+? \?\>/s", "\\1", $expr));
- $statement = str_replace("\\\"", "\"", $statement);
- return $expr . $statement;
- }
- /**
- * 抛出一个错误信息
- *
- * @param string $message
- * @return void
- */
- protected function _throwException($message)
- {
- trigger_error('DolrViews错误:'.$message);
- exit;
- }
- }
- /* vim: set expandtab: */
使用范例:
PHP:
-
- include 'DolrViews.class.php';
- $tpl=DolrViews::getInstance();//单例
- $_options=array(
- 'template_dir'=>'templates',//模板目录
- 'compile_dir'=>'templates_c',//编译目录
- 'cache_dir'=>'cache',//缓存目录
- 'caching'=>false,//是否缓存
- 'cache_lifetime'=>3600,//缓存有效期
- 'plugins_dir'=>'plugins',//插件目录
- 'tpl_suffix'=>'html',//模板后缀
- );
- $tpl->setOptions($_options);//保存如上设置
- $title="标题测试啊";
- $val=3;
- $array=array(
- array('username'=>'Joychao','password'=>'nowpass'),
- array('username'=>'DolrPHP','password'=>'password'),
- );
- $var='这里是带标签的HTML';
- //分配变量
- $tpl->assign('val',$val);
- $tpl->assign('title',$title);
- $tpl->assign('array',$array);
- //显示
- $tpl->display('index.html');
模板index.html:
-
- <$title|strip_tags:'hahah'|html2text:"nnn">
-
-
- --包含文件----------------------------
-
- ------if else------------------------
-
- do anything
-
- do another
-
- Do not
-
- ---------------------------------
- ------loop------------------------
-
-
循环内容<$dolr_index>
- 交互式显示:
-
循环中的变量:<$v.username>
-
循环中的索引$dolr_index:ccc
-
-
没有内容
-
- ---------------------------------
- --包含文件----------------------------
-
- ------------------------------
-
目录范例:
DolrViews/
|--cache //缓存目录
|--plugins
//插件目录
|--templates //模板目录
|--templates_c
//编译文件目录
|--DolrViews.classs.php //引擎主文件
|--index.php
//测试文件
目前插件只写了一个测试,插件规范是modifier_函数名.php 内容函数名:dolr_modifier_函数名($第一个参数必须[,其它参数])。范例:
- function dolr_modifier_html2text($string)
- {
- return strip_tags($string);
- }
今天刚写的,欢迎大家拍砖啊! 另外欢迎 !
原文地址:
阅读(405) | 评论(0) | 转发(0) |