不灭的焱

革命尚未成功,同志仍须努力

作者:php-note.com  发布于:2013-04-30 10:21  分类:PHP库/系统/微信  编辑

条件语句:

<!--{if $op == 'syn' || $op == 'find' || $op == 'search' || $op == 'group' || $op == 'request'}-->
这是判断语句
<!--{elseif $op == 'find'}-->
这是elseif的应用
<!--{else}-->
这是else应用语句
<!--{/if}-->

循环语句:

<!--{loop $array $a_key $a_val}-->
这是循环语句
<!--{/loop}-->

模板变量语句:

{$var}

eval应用语句:(后面的分号记得要加上)

{eval echo 1+2+3+4+5;}

语言模块的调用:(简单理解成读取了$language['china'])

{lang china}


两种引入模板文件的方法:

{subtemplate header}  //这种是静态引入, 即把header的代码直接加载在当前的缓存文件上。
{template header}  //这种是动态引入, 会通过include来引入。

 


 

Discuz的模板引擎 一个比较好的模板引擎类,很久以前就在网上找到,目前这个Discuz的模板引擎应该很老了,是DZ7.2以前的版本了,自己也用得很顺手,分享下这个模板类。

 

有两个文件,一个模板类,一个模板替换中需要用到的函数:

模板函数文件:template.func.php

<?php
/**
 * 模板替换中需要用到的函数
 */

function transamp($template) {
    $template = str_replace('&', '&', $template);
    $template = str_replace('&amp;', '&', $template);
    $template = str_replace('"', '"', $template);
    return $template;
}

function stripvtags($expr, $statement) {
    $expr = str_replace("\"", """, preg_replace("/<?=(\$.+?)?>/s", "\1", $expr));
    $statement = str_replace("\"", """, $statement);
    return $expr . $statement;
}

function addquote($var) {
    return str_replace("\"", """, preg_replace("/[([a-zA-Z0-9_-.x7f-xff]+)]/s", "['\1']", $var));
}

function stripscriptamp($s) {
    $s = str_replace('&', '&', $s);
    return "<script src="$s" type="text/javascript"></script>";
}

function stripblock($var, $s) {
    $s = str_replace('\"', '"', $s);
    $s = preg_replace("/<?=\$(.+?)?>/", "{$\1}", $s);
    preg_match_all("/<?=(.+?)?>/e", $s, $constary);
    $constadd = '';
    $constary[1] = array_unique($constary[1]);
    foreach($constary[1] as $const) {
        $constadd .= '$__' . $const  .' = ' . $const . ';';
    }
    $s = preg_replace("/<?=(.+?)?>/", "{$__\1}", $s);
    $s = str_replace('?>', "
$$var .= <<<EOF
", $s);
    $s = str_replace('<?', "
EOF;
", $s);
    return "<?
$constadd$$var = <<<EOF
" . $s . "
EOF;
?>";
}
?>

模板引擎类:

<?php
/**
 * 模板类 - 使用 Discuz 模板引擎解析
 */

require_once (DIR_ROOT . '/../function/template.func.php');
class Template {
	const DIR_SEP = DIRECTORY_SEPARATOR;

	/**
	 * 模板实例
	 *
	 * @staticvar
	 * @var object Template
	 */
	protected static $_instance;

	/**
	 * 模板参数信息
	 *
	 * @var array
	 */
	protected $_options = array();

	/**
	 * 单件模式调用方法
	 *
	 * @static
	 * @return object Template
	 */
	public static function getInstance() {
		if (!self::$_instance instanceof self)
			self::$_instance = new self();
		return self::$_instance;
	}

	/**
	 * 构造方法
	 *
	 * @return void
	 */
	private function __construct() {
		$this->_options = array(
				'template_dir' => 'templates' . self::DIR_SEP, // 模板文件所在目录
				'cache_dir' => 'templates' . self::DIR_SEP . 'cache' . self::DIR_SEP, // 缓存文件存放目录
				'auto_update' => false, // 当模板文件改动时是否重新生成缓存
				'cache_lifetime' => 0  // 缓存生命周期(分钟),为 0 表示永久
		);
	}

	/**
	 * 设定模板参数信息
	 *
	 * @param array $options
	 *        	参数数组
	 * @return void
	 */
	public function setOptions(array $options) {
		foreach ($options as $name => $value)
			$this->set($name, $value);
	}

	/**
	 * 设定模板参数
	 *
	 * @param string $name
	 *        	参数名称
	 * @param mixed $value
	 *        	参数值
	 * @return void
	 */
	public function set($name, $value) {
		switch ($name) {
			case 'template_dir' :
				$value = $this->_trimpath($value);
				if (!file_exists($value))
					$this->_throwException("未找到指定的模板目录 "$value"");
				$this->_options['template_dir'] = $value;
				break;
			case 'cache_dir' :
				$value = $this->_trimpath($value);
				if (!file_exists($value))
					$this->_throwException("未找到指定的缓存目录 "$value"");
				$this->_options['cache_dir'] = $value;
				break;
			case 'auto_update' :
				$this->_options['auto_update'] = (boolean)$value;
				break;
			case 'cache_lifetime' :
				$this->_options['cache_lifetime'] = (float)$value;
				break;
			default :
				$this->_throwException("未知的模板配置选项 "$name"");
		}
	}

	/**
	 * 通过魔术方法设定模板参数
	 *
	 * @see Template::set()
	 * @param string $name
	 *        	参数名称
	 * @param mixed $value
	 *        	参数值
	 * @return void
	 */
	public function __set($name, $value) {
		$this->set($name, $value);
	}

	/**
	 * 获取模板文件
	 *
	 * @param string $file
	 *        	模板文件名称
	 * @return string
	 */
	public function getfile($file) {
		$cachefile = $this->_getCacheFile($file);
		if (!file_exists($cachefile))
			$this->cache($file);
		return $cachefile;
	}

	/**
	 * 检测模板文件是否需要更新缓存
	 *
	 * @param string $file
	 *        	模板文件名称
	 * @param string $md5data
	 *        	模板文件 md5 校验信息
	 * @param integer $md5data
	 *        	模板文件到期时间校验信息
	 * @return void
	 */
	public function check($file, $md5data, $expireTime) {
		if ($this->_options['auto_update'] && md5_file($this->_getTplFile($file)) != $md5data)
			$this->cache($file);
		if ($this->_options['cache_lifetime'] != 0 && (time() - $expireTime >= $this->_options['cache_lifetime'] * 60))
			$this->cache($file);
	}

	/**
	 * 对模板文件进行缓存
	 *
	 * @param string $file
	 *        	模板文件名称
	 * @return void
	 */
	public function cache($file) {
		$tplfile = $this->_getTplFile($file);

		if (!is_readable($tplfile)) {
			$this->_throwException("模板文件 "$tplfile" 未找到或者无法打开");
		}

		// 取得模板内容
		$template = file_get_contents($tplfile);

		// 过滤 <!--{}-->
		$template = preg_replace("/<!--{(.+?)}-->/s", "{\1}", $template);

		// 替换语言包变量
		// $template = preg_replace("/{langs+(.+?)}/ies", "languagevar('\1')", $template);

		// 替换 PHP 换行符
		$template = str_replace("{LF}", "<?="\n"?>", $template);

		// 替换直接变量输出
		$varRegexp = "((\$[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*)" . "([[a-zA-Z0-9_-."'[]$x7f-xff]+])*)";
		$template = preg_replace("/{(\$[a-zA-Z0-9_[]'"$.x7f-xff]+)}/s", "<?=\1?>", $template);
		$template = preg_replace("/$varRegexp/es", "addquote('<?=\1?>')", $template);
		$template = preg_replace("/<?=<?=$varRegexp?>?>/es", "addquote('<?=\1?>')", $template);

		// 替换模板载入命令
		$template = preg_replace("/[

	]*{templates+([a-z0-9_]+)}[

	]*/is", "
<? include($template->getfile('\1')); ?>
", $template);
		$template = preg_replace("/[

	]*{templates+(.+?)}[

	]*/is", "
<? include($template->getfile(\1)); ?>
", $template);

		// 替换特定函数
		$template = preg_replace("/[

	]*{evals+(.+?)}[

	]*/ies", "stripvtags('<? \1 ?>','')", $template);
		$template = preg_replace("/[

	]*{echos+(.+?)}[

	]*/ies", "stripvtags('<? echo \1; ?>','')", $template);
		$template = preg_replace("/([

	]*){elseifs+(.+?)}([

	]*)/ies", "stripvtags('\1<? } elseif(\2) { ?>\3','')", $template);
		$template = preg_replace("/([

	]*){else}([

	]*)/is", "\1<? } else { ?>\2", $template);

		// 替换循环函数及条件判断语句
		$nest = 5;
		for ($i = 0; $i < $nest; $i++) {
			$template = preg_replace("/[

	]*{loops+(S+)s+(S+)}[

]*(.+?)[

]*{/loop}[

	]*/ies", "stripvtags('<? if(is_array(\1)) { foreach(\1 as \2) { ?>','\3<? } } ?>')", $template);
			$template = preg_replace("/[

	]*{loops+(S+)s+(S+)s+(S+)}[

	]*(.+?)[

	]*{/loop}[

	]*/ies", "stripvtags('<? if(is_array(\1)) { foreach(\1 as \2 => \3) { ?>','\4<? } } ?>')", $template);
			$template = preg_replace("/([

	]*){ifs+(.+?)}([

]*)(.+?)([

]*){/if}([

	]*)/ies", "stripvtags('\1<? if(\2) { ?>\3','\4\5<? } ?>\6')", $template);
		}

		// 常量替换
		$template = preg_replace("/{([a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*)}/s", "<?=\1?>", $template);

		// 删除 PHP 代码断间多余的空格及换行
		$template = preg_replace("/ ?>[

]*<? /s", " ", $template);

		// 其他替换
		$template = preg_replace("/"(http)?[w./:]+?[^"]+?&[^"]+?"/e", "transamp('\0')", $template);
		$template = preg_replace("/<script[^>]*?src="(.+?)".*?>s*</script>/ise", "stripscriptamp('\1')", $template);
		$template = preg_replace("/[

	]*{blocks+([a-zA-Z0-9_]+)}(.+?){/block}/ies", "stripblock('\1', '\2')", $template);

		// 添加 md5 及过期校验
		$md5data = md5_file($tplfile);
		$expireTime = time();
		$template = "<? if (!class_exists('template')) die('Access Denied');" . "$template->getInstance()->check('$file', '$md5data', $expireTime);" . "?>
$template";

		// 写入缓存文件
		$cachefile = $this->_getCacheFile($file);
		$makepath = $this->_makepath($cachefile);
		if ($makepath !== true)
			$this->_throwException("无法创建缓存目录 "$makepath"");
		file_put_contents($cachefile, $template);
	}

	/**
	 * 将路径修正为适合操作系统的形式
	 *
	 * @param string $path
	 *        	路径名称
	 * @return string
	 */
	protected function _trimpath($path) {
		return str_replace(array(
				'/',
				'\',
				'//',
				'\\'
		), self::DIR_SEP, $path);
	}

	/**
	 * 获取模板文件名及路径
	 *
	 * @param string $file
	 *        	模板文件名称
	 * @return string
	 */
	protected function _getTplFile($file) {
		return $this->_trimpath($this->_options['template_dir'] . self::DIR_SEP . $file);
	}

	/**
	 * 获取模板缓存文件名及路径
	 *
	 * @param string $file
	 *        	模板文件名称
	 * @return string
	 */
	protected function _getCacheFile($file) {
		$file = preg_replace('/.[a-z0-9-_]+$/i', '.cache.php', $file);
		return $this->_trimpath($this->_options['cache_dir'] . self::DIR_SEP . $file);
	}

	/**
	 * 根据指定的路径创建不存在的文件夹
	 *
	 * @param string $path
	 *        	路径/文件夹名称
	 * @return string
	 */
	protected function _makepath($path) {
		$dirs = explode(self::DIR_SEP, dirname($this->_trimpath($path)));
		$tmp = '';
		foreach ($dirs as $dir) {
			$tmp .= $dir . self::DIR_SEP;
			if (!file_exists($tmp) && !@mkdir($tmp, 0777))
				return $tmp;
		}
		return true;
	}

	/**
	 * 抛出一个错误信息
	 *
	 * @param string $message
	 * @return void
	 */
	protected function _throwException($message) {
		throw new Exception($message);
	}
}

?>