侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

PHP实现简单的模板引擎功能示例

php  /  管理员 发布于 7年前   163

本文实例讲述了PHP实现简单的模板引擎功能。分享给大家供大家参考,具体如下:

php web开发中广泛采取mvc的设计模式,controller传递给view层的数据,必须通过模板引擎才能解析出来。实现一个简单的仅仅包含if,foreach标签,解析$foo变量的模板引擎。

编写template模板类和compiler编译类。代码如下:

 '.php',//文件后缀名  'templateDir' => '../views/',//模板所在文件夹  'compileDir' => '../runtime/cache/views/',//编译后存放的目录  'suffixCompile' => '.php',//编译后文件后缀  'isReCacheHtml' => false,//是否需要重新编译成静态html文件  'isSupportPhp' => true,//是否支持php的语法  'cacheTime' => 0,//缓存时间,单位秒 ]; private $_file;//带编译模板文件 private $_valueMap = [];//键值对 private $_compiler;//编译器 public function __construct($compiler, $config = []) {  $this->_compiler = $compiler;  $this->_config = array_merge($this->_config, $config); } /**  * [assign 存储控制器分配的键值]  * @param [type] $values [键值对集合]  * @return [type]   [description]  */ public function assign($values) {  if (is_array($values)) {   $this->_valueMap = $values;  } else {   throw new \Exception('控制器分配给视图的值必须为数组!');  }  return $this; } /**  * [show 展现视图]  * @param [type] $file [带编译缓存的文件]  * @return [type]  [description]  */ public function show($file) {  $this->_file = $file;  if (!is_file($this->path())) {   throw new \Exception('模板文件'. $file . '不存在!');  }  $compileFile = $this->_config['compileDir'] . md5($file) . $this->_config['suffixCompile'];  $cacheFile = $this->_config['compileDir'] . md5($file) . '.html';  //编译后文件不存在或者缓存时间已到期,重新编译,重新生成html静态缓存  if (!is_file($compileFile) || $this->isRecompile($compileFile)) {   $this->_compiler->compile($this->path(), $compileFile, $this->_valueMap);   $this->_config['isReCacheHtml'] = true;   if ($this->isSupportPhp()) {    extract($this->_valueMap, EXTR_OVERWRITE);//从数组中将变量导入到当前的符号表   }  }  if ($this->isReCacheHtml()) {   ob_start();   ob_clean();   include($compileFile);   file_put_contents($cacheFile, ob_get_contents());   ob_end_flush();  } else {   readfile($cacheFile);  } } /**  * [isRecompile 根据缓存时间判断是否需要重新编译]  * @param [type] $compileFile [编译后的文件]  * @return boolean    [description]  */ private function isRecompile($compileFile) {  return time() - filemtime($compileFile) > $this->_config['cacheTime']; } /**  * [isReCacheHtml 是否需要重新缓存静态html文件]  * @return boolean [description]  */ private function isReCacheHtml() {  return $this->_config['isReCacheHtml']; } /**  * [isSupportPhp 是否支持php语法]  * @return boolean [description]  */ private function isSupportPhp() {  return $this->_config['isSupportPhp']; } /**  * [path 获得模板文件路径]  * @return [type] [description]  */ private function path() {  return $this->_config['templateDir'] . $this->_file . $this->_config['suffix']; }}
_valueMap['\\1']; ?>",  '',  '',  '',  "_valueMap['\\1'] as \$k => \$v) {?>",  '',  '' ]; /**  * [compile 编译模板文件]  * @param [type] $source [模板文件]  * @param [type] $destFile [编译后文件]  * @param [type] $values [键值对]  * @return [type]   [description]  */ public function compile($source, $destFile, $values) {  $this->_content = file_get_contents($source);  $this->_valueMap = $values;  if (strpos($this->_content, '{$') !== false) {   $this->_content = preg_replace($this->_patten, $this->_translation, $this->_content);  }  file_put_contents($destFile, $this->_content); }}

我们的控制器就可以调用template中的assign方法进行赋值,show方法进行模板编译了。

/*** [render 渲染模板文件]* @param [type] $file   [待编译的文件]* @param [type] $values   [键值对]* @param array $templateConfig [编译配置]* @return [type]     [description]*/protected function render($file, $values, $templateConfig = []){  $di = Container::getInstance();  //依赖注入实例化对象  $di->template = function () use ($di, $templateConfig) {   $di->compiler = 'foo\base\Compiler';   $compiler = $di->compiler;   return new \foo\base\Template($compiler, $templateConfig);  };  $di->template->assign($values)->show($file);}

Container类如下:

s[$k] = $c; } public function __get($k) {  return $this->build($this->s[$k]); } /**  * 自动绑定(Autowiring)自动解析(Automatic Resolution)  *  * @param string $className  * @return object  * @throws Exception  */ public function build($className) {    // 如果是闭包函数(closures)  if ($className instanceof \Closure) {   // 执行闭包函数   return $className($this);  }  if (isset(self::$instances[$className])) {   return self::$instances[$className];  }  /** @var ReflectionClass $reflector */  $reflector = new \ReflectionClass($className);  // 检查类是否可实例化, 排除抽象类abstract和对象接口interface  if (!$reflector->isInstantiable()) {   throw new \Exception($reflector . ': 不能实例化该类!');  }  /** @var ReflectionMethod $constructor 获取类的构造函数 */  $constructor = $reflector->getConstructor();  // 若无构造函数,直接实例化并返回  if (is_null($constructor)) {   return new $className;  }  // 取构造函数参数,通过 ReflectionParameter 数组返回参数列表  $parameters = $constructor->getParameters();  // 递归解析构造函数的参数  $dependencies = $this->getDependencies($parameters);  // 创建一个类的新实例,给出的参数将传递到类的构造函数。  $obj = $reflector->newInstanceArgs($dependencies);  self::$instances[$className] = $obj;  return $obj; } /**  * @param array $parameters  * @return array  * @throws Exception  */ public function getDependencies($parameters) {  $dependencies = [];  /** @var ReflectionParameter $parameter */  foreach ($parameters as $parameter) {   /** @var ReflectionClass $dependency */   $dependency = $parameter->getClass();   if (is_null($dependency)) {    // 是变量,有默认值则设置默认值    $dependencies[] = $this->resolveNonClass($parameter);   } else {    // 是一个类,递归解析    $dependencies[] = $this->build($dependency->name);   }  }  return $dependencies; } /**  * @param ReflectionParameter $parameter  * @return mixed  * @throws Exception  */ public function resolveNonClass($parameter) {  // 有默认值则返回默认值  if ($parameter->isDefaultValueAvailable()) {   return $parameter->getDefaultValue();  }  throw new \Exception('I have no idea what to do here.'); }}

要想以键值对的方式访问对象的属性必须实现ArrayAccess接口的四个方法,

Object基类代码如下:

public function offsetExists($offset) {  return array_key_exists($offset, get_object_vars($this));}public function offsetUnset($key) {  if (array_key_exists($key, get_object_vars($this)) ) {   unset($this->{$key});  }}public function offsetSet($offset, $value) {  $this->{$offset} = $value;}public function offsetGet($var) {  return $this->$var;}

在某一控制器中就可以调用父类Controller的render方法啦

复制代码 代码如下:
$this->render('test\index', ['name' => 'tom', 'age' => 20, 'friends' => ['jack', 'rose']], ['cacheTime' => 10]);

编写视图模板文件'test\index':

  Document 

展示模板文件视图

{$name}

{$age}

{if $age > 18}

已成年

{else if $age < 10}

小毛孩

{/if} {foreach $friends}

{^v}

{/foreach}

至此,一个简单的模板编译引擎就写好了。

更多关于PHP相关内容感兴趣的读者可查看本站专题:《PHP模板技术总结》、《PHP基于pdo操作数据库技巧总结》、《PHP运算与运算符用法总结》、《PHP网络编程技巧总结》、《PHP基本语法入门教程》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

您可能感兴趣的文章:

  • 需要使用php模板的朋友必看的很多个顶级PHP模板引擎比较分析
  • PHP原生模板引擎 最简单的模板引擎
  • PHP中MVC模式的模板引擎开发经验分享
  • php模板引擎技术简单实现
  • Pain 全世界最小最简单的PHP模板引擎 (普通版)
  • CodeIgniter使用phpcms模板引擎
  • php smarty模板引擎的6个小技巧
  • 简单的自定义php模板引擎
  • PHP的自定义模板引擎
  • 自定义min版smarty模板引擎MinSmarty.class.php文件及用法


  • 上一条:
    php简单读取.vcf格式文件的方法示例
    下一条:
    PHP实现类似于C语言的文件读取及解析功能
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(95个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客