PHP中面向对象中的模板引擎类
更新:HHH   时间:2023-1-7


<?php

/**
* 模版引擎类
*/
class Tpl
{

	//缓存目录
	protected $cacheDir = './Cache/';
	//模版目录
	protected $tplDir = './Tpl/';
	//保存变量的成员方法
	protected $vars = [];
	//缓存有效期
	protected $cacheLifeTime = 3600;


	//初始化成员属性
	public function __construct($tplDir = null ,$cacheDir = null ,$cacheLifeTime = null)
	{
		//判断缓存目录是否存在
		if (isset($tplDir)) {
			if ($this->_checkDir($tplDir)) {
				$this->tplDir = rtrim($tplDir,'/') . '/';
			}
		}
		//判断模板路径是否存在  如果不存在要创建,权限是否可写 就需要更改权限
		if (isset($cacheDir)) {
			if ($this->_checkDir($cacheDir)) {
				$this->tplDir = rtrim($cacheDir,'/') . '/';
			}
		}
		//初始化缓存时间
		if (isset($cacheLifeTime)) {
			$thsi->cacheLifeTime = $cacheLifeTime;
		}
	}

	//目录的创建以及权限的处理
	private function _checkDir($path)
	{
		//判断是否存在目录以及是否是目录
		if (!file_exists($path) || !is_dir($path)) {
			 return mkdir($path,0755,true);
		}

		//判断目录的权限是否可读可写
		if (!is_readable($path) || !is_writable($path)) {
			return chmod($path,0755);
		}

		return true;
	}

	//分配变量 主要的目的是将模板中需要处理的代码在php中替换做准备
	public function assign($key,$val)
	{
		$this->vars[$key] = $val;

	}

	//display 显示模板文件
	public function display($file,$isExecute = true ,$uri = null)
	{

	   	//获得模板路径(模板目录路径+模板文件)
	   	$tplFilePath = $this->tplDir.$file;
		//判断文件是否存在
		if (!file_exists($tplFilePath)) {
			exit('模板文件不存在');		}
		//获得编译文件路径(组合一个全新的文件名和路径)
		$cacheFile = md5($file.$uri) . '.php';

		$cacheFilePath  = $this->cacheDir . $cacheFile;

		//检测是否编译过 是否修改过模板文件 如果变编译过 而且在有效期内则不编译
		if (!file_exists($cacheFilePath)) {
			$html = $this->compile($tplFilePath);

		} else {

			//如果修改过模版文件  就需要删除原来的编译文件重新编译
			if (filemtime($tplFilePath) > filemtime($cacheFilePath)) {

				//删除原来的文件
				unlink($cacheFilePath);

				//重新编译
				$html = $this->compile($tplFilePath);

			}

			//文件创建时间+缓存有效期 > time() [当前时间], 没有过期  否则过期
			$isTimeout = (filemtime($tplFilePath) + $this->cacheLifeTime > time()) ? false : true;

			if ($isTimeout) {
				$html = $this->compile($tplFilePath);
			}
		}

		//编译
		if (isset($html)) {
			if (!file_put_contents($cacheFilePath, $html)) {
				exit('编译文件写入失败');
			}
		}

		//执行
		if ($isExecute) {
			extract($this->vars);
			include $cacheFilePath;
		}
	}

	//编译的方法  将html的php代码替换成php代码来执行 并且生成一个缓存
	protected function compile($tplFilePath)
	{
		//将整个文件读入一个字符串
		$html = file_get_contents($tplFilePath);

		//正则替换规则
		$keys = [
			'{if %%}' => '<?php if(\1): ?>',
            '{else}' => '<?php else : ?>',
            '{else if %%}' => '<?php elseif(\1) : ?>',
            '{elseif %%}' => '<?php elseif(\1) : ?>',
            '{/if}' => '<?php endif;?>',
            '{$%%}' => '<?=$\1;?>',
            '{foreach %%}' => '<?php foreach(\1) :?>',
            '{/foreach}' => '<?php endforeach;?>',
            '{for %%}' => '<?php for(\1):?>',
            '{/for}' => '<?php endfor;?>',
            '{while %%}' => '<?php while(\1):?>',
            '{/while}' => '<?php endwhile;?>',
            '{continue}' => '<?php continue;?>',
            '{break}' => '<?php break;?>',
            '{$%% = $%%}' => '<?php $\1 = $\2;?>',
            '{$%%++}' => '<?php $\1++;?>',
            '{$%%--}' => '<?php $\1--;?>',
            '{comment}' => '<?php /* ',
            '{/comment}' => ' */ ?>',
            '{/*}' => '<?php /* ',
            '{*/}' => '* ?>',
            '{section}' => '<?php ',
            '{/section}' => '?>',
			'{{%%(%%)}}' => '<?=\1(\2);?>',

			'{include %%}' => '<?php include "\1";?>',

		];

			//通过遍历 然后一一替换
		foreach ($keys as $key => $value) {
				//正则匹配替换
			$patten = '#' . str_replace('%%', '(.+)', preg_quote($key,'#')) . '#imsU';

			$replace = $value;

			//包含文件处理 include处理方式不一样
			if (stripos($patten, 'include')) {
				// 执行一个正则表达式搜索并且使用一个回调进行替换
				$html = preg_replace_callback($patten, array($this,'parseInclude'), $html);

			} else {

				$html = preg_replace($patten, $replace, $html);
			}

		}
		return $html;

	}

	protected function parseInclude($data)
	{

		$file = str_replace(['\'','"'],'',$data[1]);

		$path = $this->parsePath($file);

		$this->display($file,false);

		return '<?php  include "' . $path . '";?>';
	}

	//处理文件名  将汉字符号等统一设置为32位的加密文件名
	protected function parsePath($file)
	{

		$path = $this->cacheDir . md5($file).'.php';

		return $path;
	}

	//删除缓存文件(递归)
	public function clearCache()
	{
		self::delDir($this->cacheDir);
	}

	//递归删除缓存的文件
	public static function delDir($path)
	{
		$res = opendir($path);

		while($file = readdir($res)){
			if ($file == '.' || $file == '..') {
				continue;
			}

			$newPath = $path.'/'.$file;

			if (is_dir($newPath)) {

				self::delDir($newpath);
			} else {
				unlink($newPath);
			}
		}
	}

}


测试代码:

$tpl = new Tpl();
$tpl->assign('hello','world');
$tpl->assign('chensen','你好森林么么哒');


$tpl->display('index.html');


返回web开发教程...