首页 php框架 ThinkPHP ThinkPHP:模板引擎的详解

ThinkPHP:模板引擎的详解

Dec 16, 2019 pm 03:32 PM
thinkphp 模板引擎

ThinkPHP:模板引擎的详解

模板引擎由来

早期做PHP开发WEB应用都是把PHP代码和HTML模板混在一起,模板引擎的诞生主要就是为了解决后端与前端的完全分离(现在来看其实是属于不完全分离)的问题,让开发与美工可以分工合作(虽然实际上最终模板工作大多仍然是由后端开发人员完成),从而提高开发效率和便于维护。

伴随着PHP的快速成长,模板引擎也越来越多,但大致分为解释型和编译型两种,目前主流的模板引擎大多数是编译型的,也就是会先把模板编译成PHP文件执行,只要模板文件本身不变化,就不需要重新编译,例如老牌的Smarty。解释型的模板引擎每次执行的时候都会进行模板解析流程,例如小强(tinybutstrong)。

ThinkPHP从一开始就内置了一个基于XML标签库技术的编译型模板引擎,早期参考自Struts,并且不断在汲取新的思想不断进化。

如何选择模板引擎

目前主流框架都带有模板引擎组件或者封装了模板引擎的实现,因此选择内置的解决方案是最佳之选,功能和稳定性都有保证。目前最流行的模板引擎当属Laravel自带的Blade模板引擎,以及Symfony自带的Twig模板引擎。

通过安装模板引擎扩展,你可以在ThinkPHP中轻松使用包括Angular、Twig和Blade在内的模板引擎,甚至完全不使用模板引擎而是直接用PHP文件作为模板。

因为近几年三大前端框架(React/Vue/Angular)的流行,前后端分离开发逐渐成为主流,因此从ThinkPHP5.0开始定位为API开发而设计,导致模板引擎的概念已经被弱化了。ThinkPHP5.1版本的模板引擎进行过一次内部的重构,使得模板标签更加易用和接近PHP语法。

至少对于大部分新的应用来说,应该选择更主流的前后端分离设计,尽量减轻服务端的压力,也更方便前后端单独测试。你会在市面上不经意的看到采用Vue和ThinkPHP的产品(之前几期的ThinkPHP开发者周刊曾经报道过几个)。如果是维护一些老项目尤其是内容管理产品的时候,仍然可能会用到模板引擎。

鉴于这种情况,下一个版本的ThinkPHP框架将不会内置模板引擎,但有需要使用模板引擎的开发者仍然可以使用官方独立出来的think-template类库,具体使用可以参考这篇文章。

后面的篇幅,我们主要来总结下ThinkPHP内置的模板引擎的使用和技巧。

模板执行流程

系统内部的模板引擎调用关系如下:

视图(View) <=> 模板驱动(Driver) <=> 模板引擎(Template)

视图和模板引擎之间增加了一个驱动层,所以可以很方便的替换其它的模板引擎。通常我们在控制器中调用的assign/fetch等方法其实都是调用的think\View类的方法。当然,如果有必要,你也完全可以直接在控制器中操作模板引擎类,只是不方便切换其它模板引擎。

以fetch方法为例,我们看下最终的调用过程:

think\Controller->fetch();
think\View->fetch();
think\view\driver\Think->fetch();
think\Template->fetch();
登录后复制

如果你调用fetch方法的时候没有传入要渲染的完整模板文件名,则会在第三步的时候自动识别要渲染的模板文件。

很显然,最关键是最后一步,模板编译和执行的流程则全部由

think\Template->fetch();
登录后复制

方法完成,这个环节大体又可以分成几个流程。

1、判断和读取页面渲染缓存

如果当前模板设置了页面输出缓存并且已经渲染输出过,如果是则会读取缓存中的输出内容直接输出。

if (!empty($this->config[&#39;cache_id&#39;]) && $this->config[&#39;display_cache&#39;]) {
    // 读取渲染缓存
    $cacheContent = $cache->get($this->config[&#39;cache_id&#39;]);
    if (false !== $cacheContent) {
        echo $cacheContent;
        return;
    }
}
登录后复制

2、定位模板文件

定位实际的模板文件操作由模板引擎类的parseTemplateFile方法实现,这个方法的逻辑其实和视图驱动类的parseTemplate方法是类似的,如果最终的模板文件不存在则会抛出一个模板文件不存在的异常。

$template = $this->parseTemplateFile($template);
登录后复制

3、判断编译缓存

如果当前的模板文件已经编译过,会判断缓存是否还有效,有效的话就不用重复解析直接读取缓存的解析内容。由checkCache方法负责完成。

if (!$this->checkCache($cacheFile)) {
    // 缓存无效 重新模板编译
    $content = file_get_contents($template);
    $this->compiler($content, $cacheFile);
}
登录后复制

4、模板编译并缓存

这一步骤是模板引擎最核心的环节,也是功能最复杂的地方,由compiler方法负责完成,主要是解析当前模板文件中的模板标签语法为PHP可执行代码,然后生成一个模板解析缓存文件,也就是所谓的模板“编译”,其中使用了大量的正则表达式替换技术,虽然正则解析有一定的性能开销,但得益于一次解析多次调用的缓存原理,基本上模板解析的性能开销不会影响实际使用的性能。

模板编译方法的关键代码是parse方法,parse方法负责对模板文件中的标签进行解析,然后写入编译缓存文件,编译缓存默认使用的是文件缓存,支持扩展。

5、读取编译缓存

模板编译的过程只是生成了模板编译缓存文件,并没有真正载入模板,这一步骤就是载入模板编译缓存,然后导入模板变量。实现方法可以参考think\template\driver\File类的read方法。

public function read($cacheFile, $vars = [])
{
    $this->cacheFile = $cacheFile;
    if (!empty($vars) && is_array($vars)) {
        // 模板阵列变量分解成为独立变量
        extract($vars, EXTR_OVERWRITE);
    }
    //载入模版缓存文件
    include $this->cacheFile;
}
登录后复制

6、缓存页面输出

如果当前模板渲染的时候开启了页面输出缓存,就会这一步生成页面渲染后的输出缓存。

模板编译原理

我们来了解下ThinkPHP的模板引擎的实现原理。前面提到过,ThinkPHP的模板引擎最早源于Struts的设计理念,基于XML和标签库的技术实现。在设计模板语言的时候使用系统固定的标签来实现普通的变量输出功能(所以称之为普通标签),而利用XML标签库技术实现的动态标签用于变量的控制或者条件判断输出。

普通标签的解析是由think\Template类的parseTag方法完成的,主要实现了下面几个模板功能:

·变量输出(包括系统变量);

·函数过滤;

·变量运算;

·三元运算;

·执行函数以及输出结果;

·模板注释。

标签库采用的是动态扩展的设计方案,采用了类似XML的闭合/开放定义方式(这个其实也是目前模板引擎的一个局限所在),例如下面的这个:

// 闭合类型标签
<tagLib:tagName name="value" >
...
</tagLib:tagName>
// 开放类型标签
<tagLib:tagName name="value" />
登录后复制

tagLib就代表了一个标签库(类),后面的tagName标签就表示该标签库下面的某个标签(通常对应了标签库类的某个方法),后面的属性就是该标签支持的属性定义。具体该标签的属性和功能则完全由标签库类的这个方法来决定。

可以在模板开头明确指出,当前模板使用了哪些标签库

{taglib name="html,article" /}
登录后复制

所以要扩展模板引擎的功能只需要通过扩展一个标签库类就可以了。大多数的内容管理系统都会定义一套自己的模板二次开发标签,利用标签库功能就可以很方便的定义一套属于自己的标签功能。

系统内置了一套标签库Cx,主要用于文件包含、条件控制、循环输出等功能。内置标签库在使用的时候无需引入,而且在使用的时候可以省略标签库前缀,例如:

{foreach $list as $key=>$vo } 
    {$vo.id}:{$vo.name}
{/foreach}
登录后复制

这个模板语法相信PHP开发的很容易上手,上面的标签解析由think\template\taglib\Cx类的tagForeach方法完成,该方法的返回值是一个字符串,其实就是最终会解析成的一段包含变量的PHP可执行代码。

到这里,模板引擎的执行过程和原理现在基本就明白了,剩下的就是模板标签的解析细节,考验的就是正则表达式的掌握程度了。本文就不做深入了,有兴趣的朋友可以去看一些正则表达式的相关资料(例如这本《正则指引》,开发者周刊第14期也提供了一些在线的正则工具)。

遵循的原则

使用模板引擎,要尽量遵循几个重要的原则。

不要在模板文件中添加任何的业务逻辑

模板的作用主要是进行模板变量的控制和输出,不要在模板文件中添加业务逻辑代码。

明确指定渲染模板

养成明确指定渲染模板的好习惯,避免当方法名发生变化,或者被其它方法调用的时候发生错误。也不易受模板命名规范的影响。

变量统一赋值

使用assign方法或者在view助手函数的时候,统一一次传入模板变量。不要多次赋值,以免混乱。

系统变量无需赋值到模板

对于系统变量(包括请求变量、$_SESSION和$_SERVER等系统变量)无需进行模板变量赋值,可以直接在模板中输出。

常见问题

这里总结一下经常会遇到的一些常见问题。

修改定界符

可以通过模板配置文件修改模板标签的定界符。

例如,修改普通标签定界符

&#39;tpl_begin&#39; => &#39;{{&#39;, // 模板引擎普通标签开始标记
&#39;tpl_end&#39; => &#39;}}&#39;, // 模板引擎普通标签结束标记
登录后复制

标签库标签定界符

&#39;taglib_begin&#39; => &#39;<{&#39;, // 标签库标签开始标记
&#39;taglib_end&#39; => &#39;}>&#39;, // 标签库标签结束标记
登录后复制

保持原样输出

如果担心模板标签和JS代码产生混淆,可以使用literal标签

{literal} Hello,{$name}! {/literal}
登录后复制

页面最终会直接输出

Hello,{$name}!
登录后复制

避免输出转义

5.1版本为了避免XSS攻击,默认对模板变量的输出使用了安全转义,默认的转义函数是htmlentities,你可以通过更改default_filter配置改变默认的转义函数。

如果你不需要对某个模板变量输出进行转义(例如包含了HTML代码),可以使用:

{$data.content|raw}
登录后复制

分页输出就是一个需要输出HTML的典型例子,因此必须增加|raw。

关于模板主题

新版取消了原来的模板主题功能,因为模板主题对模板引擎来说,其实无非是一个模板目录,完全可以根据自己的需求控制。

例如

$theme = &#39;blue&#39;;
$this->fetch(&#39;/&#39; . $theme. &#39;/user/index&#39;);
登录后复制

或者动态设置模板引擎的view_path参数

$this->view->config(&#39;view_path&#39;, \think\facade\App::getModulePath(). &#39;view/&#39;. $theme . &#39;/&#39;);
登录后复制

如何关闭模板缓存

由于是编译型模板引擎,模板标签不能被直接执行,必须编译成PHP语法后才能执行,因此不能关闭模板编译缓存,模板引擎每次执行渲染的时候会检测模板文件是否有变化,当模板文件的修改时间超过模板编译缓存的修改时间后,模板引擎会自动更新编译缓存。

但你可以强制模板引擎每次都重新编译,只需要在配置文件中设置

&#39;tpl_cache&#39; => false, // 关闭模板缓存
登录后复制

使用PHP作为模板引擎

如果不希望使用内置的模板引擎,直接使用PHP作为模板引擎,可以配置

&#39;type&#39; => &#39;php&#39;,
登录后复制

配置使用PHP作为模板引擎的话,是不会生成模板编译缓存的。

如何使用第三方模板引擎

系统支持扩展其它的第三方模板引擎,你只需要开发一个模板引擎驱动,目前已经支持的第三方模板引擎包括Smarty、Twig和Blade。

如何跨模块输出模板

要渲染一个跨模块的模板文件,你需要使用

// 渲染user模块的模板文件
$this->fetch(&#39;User@order/index&#39;);
登录后复制

是否支持变量运算

可以直接在模板文件中进行变量运算而不需要在控制器中进行运算后再赋值都模板变量输出。

{$score1+$score2}
{$count++}
登录后复制

文件包含是否支持变量

include标签可以支持传入变量,但只能使用

{include file="$file" /}
登录后复制

而不能使用

{include file="file_$name" /}
登录后复制

可以支持模板输出替换么

支持两个方式对模板进行输出替换,如果需要对模板文件的内容进行替换,可以配置:

&#39;tpl_replace_string&#39;  =>  [
    &#39;__STATIC__&#39;=>&#39;/static&#39;,
&#39;__JS__&#39; => &#39;/static/javascript&#39;,
]
登录后复制

如果是对模板渲染输出的内容进行替换,可以在控制器中使用视图过滤功能:

public function index()
{
    // 使用视图输出过滤
    return $this->filter(function($content){
    return str_replace("\r\n",&#39;<br/>&#39;,$content);
    })->fetch();
}
登录后复制

模板继承的block是否支持嵌套

目前模板继承的block无法支持嵌套功能,你应该使用其它方式解决。

众多ThinkPHP入门教程,尽在PHP中文网,欢迎在线学习!

本文转自:https://blog.thinkphp.cn/902998

以上是ThinkPHP:模板引擎的详解的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

thinkphp项目怎么运行 thinkphp项目怎么运行 Apr 09, 2024 pm 05:33 PM

运行 ThinkPHP 项目需要:安装 Composer;使用 Composer 创建项目;进入项目目录,执行 php bin/console serve;访问 http://localhost:8000 查看欢迎页面。

thinkphp有几个版本 thinkphp有几个版本 Apr 09, 2024 pm 06:09 PM

ThinkPHP 拥有多个版本,针对不同 PHP 版本而设计。主要版本包括 3.2、5.0、5.1 和 6.0,而次要版本用于修复 bug 和提供新功能。当前最新稳定版本为 ThinkPHP 6.0.16。在选择版本时,需考虑 PHP 版本、功能需求和社区支持。建议使用最新稳定版本以获得最佳性能和支持。

thinkphp怎么运行 thinkphp怎么运行 Apr 09, 2024 pm 05:39 PM

ThinkPHP Framework 的本地运行步骤:下载并解压 ThinkPHP Framework 到本地目录。创建虚拟主机(可选),指向 ThinkPHP 根目录。配置数据库连接参数。启动 Web 服务器。初始化 ThinkPHP 应用程序。访问 ThinkPHP 应用程序 URL 运行。

laravel和thinkphp哪个好 laravel和thinkphp哪个好 Apr 09, 2024 pm 03:18 PM

Laravel 和 ThinkPHP 框架的性能比较:ThinkPHP 性能通常优于 Laravel,专注于优化和缓存。Laravel 性能良好,但对于复杂应用程序,ThinkPHP 可能更适合。

开发建议:如何利用ThinkPHP框架实现异步任务 开发建议:如何利用ThinkPHP框架实现异步任务 Nov 22, 2023 pm 12:01 PM

《开发建议:如何利用ThinkPHP框架实现异步任务》随着互联网技术的迅猛发展,Web应用程序对于处理大量并发请求和复杂业务逻辑的需求也越来越高。为了提高系统的性能和用户体验,开发人员常常会考虑利用异步任务来执行一些耗时操作,比如发送邮件、处理文件上传、生成报表等。在PHP领域,ThinkPHP框架作为一款流行的开发框架,提供了一些便捷的方式来实现异步任务。

thinkphp怎么安装 thinkphp怎么安装 Apr 09, 2024 pm 05:42 PM

ThinkPHP 安装步骤:准备 PHP、Composer、MySQL 环境。使用 Composer 创建项目。安装 ThinkPHP 框架及依赖项。配置数据库连接。生成应用代码。启动应用并访问 http://localhost:8000。

thinkphp性能怎么样 thinkphp性能怎么样 Apr 09, 2024 pm 05:24 PM

ThinkPHP 是一款高性能的 PHP 框架,具备缓存机制、代码优化、并行处理和数据库优化等优势。官方性能测试显示,它每秒可处理超过 10,000 个请求,实际应用中被广泛用于京东商城、携程网等大型网站和企业系统。

开发建议:如何利用ThinkPHP框架进行API开发 开发建议:如何利用ThinkPHP框架进行API开发 Nov 22, 2023 pm 05:18 PM

开发建议:如何利用ThinkPHP框架进行API开发随着互联网的不断发展,API(ApplicationProgrammingInterface)的重要性也日益凸显。API是不同应用程序之间进行通信的桥梁,它可以实现数据共享、功能调用等操作,为开发者提供了相对简单和快速的开发方式。而ThinkPHP框架作为一款优秀的PHP开发框架,具有高效、可扩展和易用

See all articles