本文作者:温文曦

PHP 轻量级模板引擎

温文曦 4周前 ( 11-01 13:06 ) 552 2条评论 百度已收录
PHP 轻量级模板引擎摘要: 模板引擎类轻、灵活、快速、安全,它编译模板以优化 PHP 代码。下面我将为您提供完整的源代码和如何使用模板引擎类的示例。为什么我需要模板引擎?模板引擎使设计代码远离应用程序代码,仅...

模板引擎类轻、灵活、快速、安全,它编译模板以优化 PHP 代码。

下面我将为您提供完整的源代码和如何使用模板引擎类的示例。

为什么我需要模板引擎?

模板引擎使设计代码远离应用程序代码,仅此原因就是好的做法,并且遵循许多设计模式。使用模板引擎完全取决于您,如果您希望保持代码干净整洁,那么使用模板引擎是理想的选择。

如果您正在使用 MVC 模式,那么使用模板引擎是一个好主意。


代码

创建一个新文件并命名它Template.php并添加:

<?php class Template {

	static $blocks = array();
	static $cache_path = 'cache/';
	static $cache_enabled = FALSE;

	static function view($file, $data = array()) {
		$cached_file = self::cache($file);
	    extract($data, EXTR_SKIP);
	   	require $cached_file;
	}

	static function cache($file) {
		if (!file_exists(self::$cache_path)) {
		  	mkdir(self::$cache_path, 0744);
		}
	    $cached_file = self::$cache_path . str_replace(array('/', '.html'), array('_', ''), $file . '.php');
	    if (!self::$cache_enabled || !file_exists($cached_file) || filemtime($cached_file) < filemtime($file)) {
			$code = self::includeFiles($file);
			$code = self::compileCode($code);
	        file_put_contents($cached_file, '<?php class_exists(\'' . __CLASS__ . '\') or exit; ?>' . PHP_EOL . $code);
	    }
		return $cached_file;
	}

	static function clearCache() {
		foreach(glob(self::$cache_path . '*') as $file) {
			unlink($file);
		}
	}

	static function compileCode($code) {
		$code = self::compileBlock($code);
		$code = self::compileYield($code);
		$code = self::compileEscapedEchos($code);
		$code = self::compileEchos($code);
		$code = self::compilePHP($code);
		return $code;
	}

	static function includeFiles($file) {
		$code = file_get_contents($file);
		preg_match_all('/{% ?(extends|include) ?\'?(.*?)\'? ?%}/i', $code, $matches, PREG_SET_ORDER);
		foreach ($matches as $value) {
			$code = str_replace($value[0], self::includeFiles($value[2]), $code);
		}
		$code = preg_replace('/{% ?(extends|include) ?\'?(.*?)\'? ?%}/i', '', $code);
		return $code;
	}

	static function compilePHP($code) {
		return preg_replace('~\{%\s*(.+?)\s*\%}~is', '<?php $1 ?>', $code);
	}

	static function compileEchos($code) {
		return preg_replace('~\{{\s*(.+?)\s*\}}~is', '<?php echo $1 ?>', $code);
	}

	static function compileEscapedEchos($code) {
		return preg_replace('~\{{{\s*(.+?)\s*\}}}~is', '<?php echo htmlentities($1, ENT_QUOTES, \'UTF-8\') ?>', $code);
	}

	static function compileBlock($code) {
		preg_match_all('/{% ?block ?(.*?) ?%}(.*?){% ?endblock ?%}/is', $code, $matches, PREG_SET_ORDER);
		foreach ($matches as $value) {
			if (!array_key_exists($value[1], self::$blocks)) self::$blocks[$value[1]] = '';
			if (strpos($value[2], '@parent') === false) {
				self::$blocks[$value[1]] = $value[2];
			} else {
				self::$blocks[$value[1]] = str_replace('@parent', self::$blocks[$value[1]], $value[2]);
			}
			$code = str_replace($value[0], '', $code);
		}
		return $code;
	}

	static function compileYield($code) {
		foreach(self::$blocks as $block => $value) {
			$code = preg_replace('/{% ?yield ?' . $block . ' ?%}/', $value, $code);
		}
		$code = preg_replace('/{% ?yield ?(.*?) ?%}/i', '', $code);
		return $code;
	}

}
?>


请记住更新$cache_enabled$cache_path变量,缓存当前已禁用用于开发目的,您可以在代码已准备就绪时启用此功能。



如何使用

创建一个新文件并命名index.php

<?php
include 'Template.php';
Template::view('index.html');
?>

创建新的 HTML 文件并命名 layout.html 

<!DOCTYPE html><html>
	<head>
		<title>{% yield title %}</title>
        <meta charset="utf-8">
	</head>
	<body>
    {% yield content %}    </body></html>

这是我们将用于此示例的布局。

现在创建index.html 

{% extends layout.html %}
{% block title %}Home Page{% endblock %}
{% block content %}<h1>Home</h1><p>Welcome to the home page!</p>{% endblock %}

现在给它一个尝试, 导航到index. php文件, 你应该看到输出, 相当真棒, 对不对?

但是,如果我们想要在模板文件中使用变量,那会怎么样呢?简单,将index.php 文件中的模板代码更改为:

Template::view('about.html', [
    'title' => 'Home Page',
    'colors' => ['red','blue','green']]);

然后,我们可以使用它如下:

{% extends layout.html %}

{% block title %}{{ $title }}{% endblock %}

{% block content %}<h1>Home</h1><p>Welcome to the home page, list of colors:</p><ul>
    {% foreach($colors as $color): %}    <li>{{ $color }}</li>
    {% endforeach; %}</ul>{% endblock %}

如果我们想要确保输出安全,那该如何?替换下面的代码:

{{ $output }}

替换为:

{{{ $output }}}

这将使用 html 特别字符函数转义输出。

扩展:

{% block content %}
@parent<p>Extends content block!</p>{% endblock %}

包括其他模板文件:

{% include forms.html %}



结论

模板引擎在大型项目中非常有用,它将使您的设计代码远离您的应用程序代码,我在我开发的自定义 MVC 框架中使用此类,发现导航到模板文件进行编辑更容易,其他人发现代码要读得更清楚。

您可以在项目中自由使用此模板类。


文章版权及转载声明

作者:温文曦本文地址:https://www.vience.cn/blog/516.html发布于 4周前 ( 11-01 13:06 )
文章转载或复制请以超链接形式并注明出处文曦博客

赞(3
阅读
分享

发表评论

快捷回复:

评论列表 (有 2 条评论,552人围观)参与讨论
网友昵称:惠州注册公司
惠州注册公司 游客2020-11-02沙发 回复
又发现一个好站,收藏了~以后会经常光顾的
网友昵称:温文曦
温文曦 博主2020-11-03 回复
@惠州注册公司 欢迎,感谢支持