PHP模板二(仿DEDE)

今天看了下正则表达式,忽然觉得可以把我现在手上的企业建站系统改一下。不过改来改去觉得还是仿DEDE的方式好一点。

于是开始看DEDE是如何处理标签的。于是经过一上午的学习,我发现了一个正则表达式

/({t:*[^{]*\/}|{t:*[^}]*}([^{]|(?R))*{\/t:.*?})/i
但是对我于这个系统来说,那就简单得多,所以参照这个我做了以下的正则表达式

 

private $preg_string = "/(<m:*[^<]*>|<\/m:*[^<]*>)/si";


 

//tag数组
$tag_arr = array();
//文件内容
$file_content = file_get_contents($file);
//正则解析
preg_match_all($this->preg_string , $file_content , $m);
foreach($m[0] as $key => $value){
	//标签字符串
	$tag_arr[$key]['str'] = $value;
	$vs = explode(':' , $value);
	//标签名
	$va = explode(' ' , $vs[1]);
	if(strpos($value , '/')==1){
		$tag_arr[$key]['tag_name'] = 'end';
	}
	else{
		$tag_arr[$key]['tag_name'] = $va[0];
	}
	
	unset($va[0]);
	foreach($va as $name => $item){
		$val = strtr($item , array('"'=>'' , '\''=>'' , '>'=>'' , '/>'=>''));
		$val_arr = explode('=' , $val);
		$property[$val_arr[0]] = $val_arr[1];
	}
	//标签属性数组
	$tag_arr[$key]['property'] = $property;
	unset($property);
}
var_dump($tag_arr);

$tag_arr数组的格式如下

PHP模板二(仿DEDE)_第1张图片

然后用PHP的str_replace方式替换$tag_arr['str']

以下是源码

stemplate.class.php

<?php
class stemplate{
	//源文件目录
	public $template_dir = './template/';
	//缓存目录 
	public $cache_dir = './cache/';
	//编译目录
	public $template_c_dir = './template_c/';
	//编译文件
	private $template_c_file = '';
	//缓存文件
	private $cache_file = '';
	//源文件
	public $template_file = '';
	//核心正则
	private $preg_string = "/(<m:*[^<]*>|<\/m:*[^<]*>)/si";
	/**
	 *显示页面
	 *@param $file String 文件名
	 */
	public function display($file){
		echo $this->fetch($file);
	}
	
	/**
	 *将页面写入缓冲区然后输入
	 *@param $file String 文件名
	 */
	public function fetch($file){
		//替换内容
		$content = '';
		//模板文件全路径
		$template_file = $this->template_dir . $file;
		//模板文件名
		$this->template_file = $file;
		if(file_exists($template_file)){
			//分析
			$content = $this->token($template_file);
		}
		else{
			exit($template_file . '--模板文件不存在');
		}
		//将文件缓存
		$this->store_file($content , 'complie');
		//导入到当前
		include $this->template_c_dir . $this->template_c_file;
	}
	
	/**
	 *分析内容
	 *@return $complie_content String 编译内容
	 *@param $file String 文件名
	 */
	private function token($file){
		//tag数组
		$tag_arr = array();
		//文件内容
		$file_content = file_get_contents($file);
		//正则解析
		preg_match_all($this->preg_string , $file_content , $m);
		foreach($m[0] as $key => $value){
			//标签字符串
			$tag_arr[$key]['str'] = $value;
			$vs = explode(':' , $value);
			//标签名
			$va = explode(' ' , $vs[1]);
			if(strpos($value , '/')==1){
				$tag_arr[$key]['tag_name'] = 'end';
			}
			else{
				$tag_arr[$key]['tag_name'] = $va[0];
			}
			
			unset($va[0]);
			foreach($va as $name => $item){
				$val = strtr($item , array('"'=>'' , '\''=>'' , '>'=>'' , '/>'=>''));
				$val_arr = explode('=' , $val);
				$property[$val_arr[0]] = $val_arr[1];
			}
			//标签属性数组
			$tag_arr[$key]['property'] = $property;
			unset($property);
		}
		var_dump($tag_arr);
		$complie_content = $this->token_array($tag_arr , $file_content);
		
		return $complie_content;
	}
	
	/**
	 *返回替换标签后的内容
	 *@return $complie_content String 编译内容
	 *@param $src_array String 属性数组
	 *@param $content String 文件内容
	 */
	private function token_array($src_array , $content){
		$file_desc_content = $content;
		foreach($src_array as $value){
			if($value['tag_name'] == 'end'){
				$file_desc_content = str_replace($value['str'] , '<?php } ?>' , $file_desc_content);
			}
			else{
				//导入标签类
				require_once './m.class.php';
				$m_class    = new m();
				$m_function = '_' . $value['tag_name'];
				if(method_exists($m_class, $m_function)){
					$tag_string = '';
					if($value['tag_name'] == 'include'){
						$tag_string = $m_class->$m_function($value['property']['file'] , $this->template_dir);
					}
					else{
						$tag_string = $m_class->$m_function($value['property']);
					}
					$file_desc_content = str_replace($value['str'] , $tag_string , $file_desc_content);
					unset($tag_string);
				}
			}
		}
		return $file_desc_content;
	}
	
	/**
	 *储存文件到编译,缓存
	 *@param $content string 内容
	 *@param $store_type string 方式
	 */
	public function store_file($content , $store_type = 'cache'){
		$desc_file = '';
		if($store_type == 'cache'){
			$this->cache_file = md5($this->template_file) . $this->template_file . '.html';
			$desc_file        = $this->cache_dir . $this->cache_file;
		}
		else{
			$this->template_c_file = md5($this->template_file) . $this->template_file . '.php';
			$desc_file             = $this->template_c_dir . $this->template_c_file;
		}
		$fp = fopen($desc_file , 'w') or die('can not open file');
		fputs($fp,$content);
		fclose($fp);
		unset($fp);
	}
}
?>

index.php

<?php

require './stemplate.class.php';

$template = new stemplate();

$template->display('index.htm');

index.htm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<title>模板</title>
</head>

<body>
<b>正常输出</b><br/>
<?php echo '正常的PHP输出'; ?><br/>
<b>foreach循环</b><br/>
<?php $temp_arr = array('aa' , 'bbb'); ?>
<m:foreach from='$temp_arr' value='cc'>
	<td><m:field name='cc' /></td>
</m:foreach>
</body>
</html>

m.class.php

<?php
class m{
	public function _foreach($property=null){
		$from = $property['from'];
		$value = $property['value'];
		$content = "<?php foreach($from as \$$value){ ?>";
		return $content;
	}
	
	public function _field($property=null){
		return "<?php echo \${$property['name']}; ?>";
	}
}


你可能感兴趣的:(PHP,String,正则表达式,function,File)