ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 快速入门(七):视图和模板 本章主要来学习视图和模板的用法。 前面只是在控制器方法里面直接输出而没有使用视图模板功能,从现在开始来了解下如何把变量赋值到模板,并渲染输出,主要内容包括: - - [模板输出](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/147290#u6A21u677Fu8F93u51FA) - [分页输出](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/147290#u5206u9875u8F93u51FA) - [公共模板](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/147290#u516Cu5171u6A21u677F) - [模板定位](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/147290#u6A21u677Fu5B9Au4F4D) - [模板布局](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/147290#u6A21u677Fu5E03u5C40) - [标签定制](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/147290#u6807u7B7Eu5B9Au5236) - [输出替换](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/147290#u8F93u51FAu66FFu6362) - [渲染内容](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/147290#u6E32u67D3u5185u5BB9) - [助手函数](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/147290#u52A9u624Bu51FDu6570) ## 模板输出 首先来看如何输出一个数据集,我们修改`User`控制器的`index`方法如下: ``` <pre class="calibre18"> ``` <span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">controller</span>; <span class="hljs-keyword">use</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>\<span class="hljs-title">User</span> <span class="hljs-title">as</span> <span class="hljs-title">UserModel</span>; <span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Controller</span>; <span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Controller</span></span>{ <span class="hljs-comment">// 获取用户数据列表并输出</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span><span class="hljs-number">()</span></span>{ <span class="hljs-regexp">$list</span> = UserModel::all(); <span class="hljs-regexp">$this</span>->assign(<span class="hljs-string">'list'</span>, <span class="hljs-regexp">$list</span>); <span class="hljs-regexp">$this</span>->assign(<span class="hljs-string">'count'</span>, count(<span class="hljs-regexp">$list</span>)); <span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->fetch(); } }</span> ``` ``` 这里的`User`控制器和之前模型章节有所不同,继承了系统的`\think\Controller`类,该类对视图类的方法进行了封装,所以可以在无需实例化视图类的情况下,直接调用视图类的相关方法,包括: 方法 描述 assign 模板变量赋值 fetch 渲染模板文件 display 渲染内容 engine 初始化模板引擎这里用到的其中两个方法`assign`和`fetch`,也是最常用的两个方法。 `assign`方法可以把任何类型的变量赋值给模板,关键在于模板中如何输出,不同的变量类型需要采用不同的标签输出。 前面我们已经学习过,`fetch`方法默认渲染输出的模板文件应该是当前控制器和操作对应的模板,也就是: ``` <pre class="calibre18"> ``` application/<span class="hljs-keyword">index</span>/view/user/<span class="hljs-keyword">index</span>.html ``` ``` 接下来,定义视图文件的内容,采用`volist`标签输出数据集: ``` <pre class="calibre18"> ``` <span class="hljs-regexp"><!doctype html></span><span class="hljs-regexp"><<span class="hljs-operator">html</span> <span class="hljs-operator">lang</span>=<span class="hljs-string">"en"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">head</span>></span><span class="hljs-regexp"><<span class="hljs-operator">meta</span> <span class="hljs-operator">charset</span>=<span class="hljs-string">"UTF-8"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">title</span>></span>查看用户列表<span class="hljs-regexp"></<span class="hljs-operator">title</span>></span><span class="hljs-regexp"><<span class="hljs-operator">style</span>></span><span class="css"><span class="hljs-regexp">body</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#333</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">font</span>:<span class="hljs-string"> <span class="hljs-number">16px</span> Verdana, <span class="hljs-operator">"Helvetica Neue"</span>, helvetica, Arial, <span class="hljs-operator">'Microsoft YaHei'</span>, sans-serif</span></span>; <span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"> <span class="hljs-number">0px</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">20px</span></span></span>; }</span><span class="hljs-regexp">a</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#868686</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">cursor</span>:<span class="hljs-string"> pointer</span></span>; }</span><span class="hljs-operator"><span class="hljs-title1">a</span>:<span class="hljs-string">hover{ text-decoration: underline</span></span>; } <span class="hljs-regexp">h2</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#4288ce</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">font-weight</span>:<span class="hljs-string"> <span class="hljs-number">400</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">6px</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"> <span class="hljs-number">6px</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">font-size</span>:<span class="hljs-string"> <span class="hljs-number">28px</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">border-bottom</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>; }</span><span class="hljs-regexp">div</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"><span class="hljs-number">8px</span></span></span>; }</span><span class="hljs-regexp">.info</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">12px</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">border-bottom</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>; }</span><span class="hljs-regexp">.copyright</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">margin-top</span>:<span class="hljs-string"> <span class="hljs-number">24px</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">12px</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">border-top</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>; }</span></span><span class="hljs-regexp"></<span class="hljs-operator">style</span>></span><span class="hljs-regexp"></<span class="hljs-operator">head</span>></span><span class="hljs-regexp"><<span class="hljs-operator">body</span>></span><span class="hljs-regexp"><<span class="hljs-operator">h2</span>></span>用户列表({$count})<span class="hljs-regexp"></<span class="hljs-operator">h2</span>></span> {volist name="list" id="user" } <span class="hljs-regexp"><<span class="hljs-operator">div</span> <span class="hljs-operator">class</span>=<span class="hljs-string">"info"</span>></span> ID:{$user.id}<span class="hljs-regexp"><<span class="hljs-operator">br</span>/></span> 昵称:{$user.nickname}<span class="hljs-regexp"><<span class="hljs-operator">br</span>/></span> 邮箱:{$user.email}<span class="hljs-regexp"><<span class="hljs-operator">br</span>/></span> 生日:{$user.birthday}<span class="hljs-regexp"><<span class="hljs-operator">br</span>/></span><span class="hljs-regexp"></<span class="hljs-operator">div</span>></span> {/volist} <span class="hljs-regexp"><<span class="hljs-operator">div</span> <span class="hljs-operator">class</span>=<span class="hljs-string">"copyright"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">a</span> <span class="hljs-operator">title</span>=<span class="hljs-string">"官方网站"</span> <span class="hljs-operator">href</span>=<span class="hljs-string">"http://www.thinkphp.cn"</span>></span>ThinkPHP<span class="hljs-regexp"></<span class="hljs-operator">a</span>></span><span class="hljs-regexp"><<span class="hljs-operator">span</span>></span>V5<span class="hljs-regexp"></<span class="hljs-operator">span</span>></span><span class="hljs-regexp"><<span class="hljs-operator">span</span>></span>{ 十年磨一剑-为API开发设计的高性能框架 }<span class="hljs-regexp"></<span class="hljs-operator">span</span>></span><span class="hljs-regexp"></<span class="hljs-operator">div</span>></span><span class="hljs-regexp"></<span class="hljs-operator">body</span>></span><span class="hljs-regexp"></<span class="hljs-operator">html</span>></span> ``` ``` `ThinkPHP5.0`默认使用的是一个内置的编译型模板引擎,包含了一系列的模板标签,我们会陆续介绍一些常用的标签用法。 index方法给模板赋值了两个变量`count`和`list`,分别是标量和二维数组,标量的输出很简单,使用: `{$count}`便可,一看就明白。 二维数组通常使用`volist`标签输出。 ``` <pre class="calibre18"> ``` {volist name=<span class="hljs-string">"list"</span> id=<span class="hljs-string">"user"</span>} ID:{<span class="hljs-regexp">$user</span>.id}<br/> 昵称:{<span class="hljs-regexp">$user</span>.nickname}<br/> 邮箱:{<span class="hljs-regexp">$user</span>.email}<br/> 生日:{<span class="hljs-regexp">$user</span>.birthday}<br/> ------------------------<br/> {/volist} ``` ``` `volist`标签的`name`属性就是模板变量的名称,`id`属性则是定义每次循环输出的变量,在volist标签中间使用`{$user.id}`表示输出当前用户的id属性,以此类推下面的内容则依次输出用户的相关属性。 ``` <pre class="calibre18"> ``` ID:{<span class="hljs-regexp">$user</span>.id}<br/> 昵称:{<span class="hljs-regexp">$user</span>.nickname}<br/> 邮箱:{<span class="hljs-regexp">$user</span>.email}<br/> 生日:{<span class="hljs-regexp">$user</span>.birthday}<br/> ``` ``` 来看下实际的输出效果,访问URL地址: ``` <pre class="calibre18"> ``` <span class="hljs-string">http:</span> <span class="hljs-comment">//tp5.com/user/index</span> ``` ``` 就可以看到页面输出结果如图: ![](https://img.kancloud.cn/f8/50/f85016b4a0cb477df792df808b75cfc1_476x462.png) 当然,实际看到的数据可能有所出入。 ## 分页输出 可以很简单的输出用户的分页数据,控制器`index`方法修改为: ``` <pre class="calibre18"> ``` <span class="hljs-comment">// 获取用户数据列表</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span><span class="hljs-number">()</span></span>{ <span class="hljs-comment">// 分页输出列表 每页显示3条数据</span><span class="hljs-regexp">$list</span> = UserModel::paginate(<span class="hljs-number">3</span>); <span class="hljs-regexp">$this</span>->assign(<span class="hljs-string">'list'</span>,<span class="hljs-regexp">$list</span>); <span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->fetch(); } ``` ``` 模板文件修改为: ``` <pre class="calibre18"> ``` <link rel=<span class="hljs-string">"stylesheet"</span> href=<span class="hljs-string">"/static/bootstrap/css/bootstrap.min.css"</span> /> <h2>用户列表({<span class="hljs-regexp">$list</span>->total()})</h2> {volist name=<span class="hljs-string">"list"</span> id=<span class="hljs-string">"user"</span>} ID:{<span class="hljs-regexp">$user</span>.id}<br/> 昵称:{<span class="hljs-regexp">$user</span>.nickname}<br/> 邮箱:{<span class="hljs-regexp">$user</span>.email}<br/> 生日:{<span class="hljs-regexp">$user</span>.birthday}<br/> ------------------------<br/> {/volist} {<span class="hljs-regexp">$list</span>->render()} ``` ``` > 注意,由于演示需要,在模板中引入了bootstrap样式文件。请按照所示位置存放。 多插入一些数据后,访问下面的地址: ``` <pre class="calibre18"> ``` <span class="hljs-string">http:</span> <span class="hljs-comment">//tp5.com/user/index</span> ``` ``` 后可以看到输出如图所示: ![](https://img.kancloud.cn/44/48/4448a054fdf482951dc3c8ef27b5378f_476x600.png) ## 公共模板 加上之前定义的创建用户的模板,现在已经有两个模板文件了,为了避免重复定义模板,可以把模板的公共头部和尾部分离出来,便于维护。 我们把模板文件拆分为三部分: ``` <pre class="calibre18"> ``` application<span class="hljs-regexp">/index/</span>view<span class="hljs-regexp">/user/</span>header.html application<span class="hljs-regexp">/index/</span>view<span class="hljs-regexp">/user/</span>index.html application<span class="hljs-regexp">/index/</span>view<span class="hljs-regexp">/user/</span>footer.html ``` ``` `header.html`内容为: ``` <pre class="calibre18"> ``` <span class="hljs-regexp"><!doctype html></span><span class="hljs-regexp"><<span class="hljs-operator">html</span> <span class="hljs-operator">lang</span>=<span class="hljs-string">"en"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">head</span>></span><span class="hljs-regexp"><<span class="hljs-operator">meta</span> <span class="hljs-operator">charset</span>=<span class="hljs-string">"UTF-8"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">title</span>></span>查看用户列表<span class="hljs-regexp"></<span class="hljs-operator">title</span>></span><span class="hljs-regexp"><<span class="hljs-operator">style</span>></span><span class="css"><span class="hljs-regexp">body</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#333</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">font</span>:<span class="hljs-string"> <span class="hljs-number">16px</span> Verdana, <span class="hljs-operator">"Helvetica Neue"</span>, helvetica, Arial, <span class="hljs-operator">'Microsoft YaHei'</span>, sans-serif</span></span>; <span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"> <span class="hljs-number">0px</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">20px</span></span></span>; }</span><span class="hljs-regexp">a</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#868686</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">cursor</span>:<span class="hljs-string"> pointer</span></span>; }</span><span class="hljs-operator"><span class="hljs-title1">a</span>:<span class="hljs-string">hover{ text-decoration: underline</span></span>; } <span class="hljs-regexp">h2</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#4288ce</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">font-weight</span>:<span class="hljs-string"> <span class="hljs-number">400</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">6px</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"> <span class="hljs-number">6px</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">font-size</span>:<span class="hljs-string"> <span class="hljs-number">28px</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">border-bottom</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>; }</span><span class="hljs-regexp">div</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"><span class="hljs-number">8px</span></span></span>; }</span><span class="hljs-regexp">.info</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">12px</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">border-bottom</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>; }</span><span class="hljs-regexp">.copyright</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">margin-top</span>:<span class="hljs-string"> <span class="hljs-number">24px</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">12px</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">border-top</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>; }</span></span><span class="hljs-regexp"></<span class="hljs-operator">style</span>></span><span class="hljs-regexp"></<span class="hljs-operator">head</span>></span><span class="hljs-regexp"><<span class="hljs-operator">body</span>></span> ``` ``` `footer.html`内容为: ``` <pre class="calibre18"> ``` <span class="hljs-regexp"><<span class="hljs-operator">div</span> <span class="hljs-operator">class</span>=<span class="hljs-string">"copyright"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">a</span> <span class="hljs-operator">title</span>=<span class="hljs-string">"官方网站"</span> <span class="hljs-operator">href</span>=<span class="hljs-string">"http://www.thinkphp.cn"</span>></span>ThinkPHP<span class="hljs-regexp"></<span class="hljs-operator">a</span>></span><span class="hljs-regexp"><<span class="hljs-operator">span</span>></span>V5<span class="hljs-regexp"></<span class="hljs-operator">span</span>></span><span class="hljs-regexp"><<span class="hljs-operator">span</span>></span>{ 十年磨一剑-为API开发设计的高性能框架 }<span class="hljs-regexp"></<span class="hljs-operator">span</span>></span><span class="hljs-regexp"></<span class="hljs-operator">div</span>></span><span class="hljs-regexp"></<span class="hljs-operator">body</span>></span><span class="hljs-regexp"></<span class="hljs-operator">html</span>></span> ``` ``` `index.html`内容为: ``` <pre class="calibre18"> ``` {include file=<span class="hljs-string">"user/header"</span> /} <h2>用户列表({<span class="hljs-regexp">$count</span>})</h2> {volist name=<span class="hljs-string">"list"</span> id=<span class="hljs-string">"user"</span> } <div class=<span class="hljs-string">"info"</span>> ID:{<span class="hljs-regexp">$user</span>.id}<br/> 昵称:{<span class="hljs-regexp">$user</span>.nickname}<br/> 邮箱:{<span class="hljs-regexp">$user</span>.email}<br/> 生日:{<span class="hljs-regexp">$user</span>.birthday}<br/> </div> {/volist} {include file=<span class="hljs-string">"user/footer"</span> /} ``` ``` 公共头部模板文件中可能存在一些变量,例如这里的页面标题不同的页面会有不同,可以使用 ``` <pre class="calibre18"> ``` {<span class="hljs-keyword">include</span> <span class="hljs-keyword">file</span>=<span class="hljs-string">"user/header"</span> title=<span class="hljs-string">"查看用户列表"</span> <span class="hljs-regexp">/}</span> ``` ``` 然后把头部模板文件中的 ``` <pre class="calibre18"> ``` <span class="hljs-regexp"><<span class="hljs-operator">title</span>></span>查看用户列表<span class="hljs-regexp"></<span class="hljs-operator">title</span>></span> ``` ``` 改为: ``` <pre class="calibre18"> ``` <span class="hljs-regexp"><<span class="hljs-operator">title</span>></span>[title]<span class="hljs-regexp"></<span class="hljs-operator">title</span>></span> ``` ``` 再次访问页面可以看到输出结果: ![](https://img.kancloud.cn/5b/14/5b1428373ea05fac9eb233d35dca4759_885x746.png) 如果需要传递多个变量,则使用多个属性即可,例如: ``` <pre class="calibre18"> ``` {<span class="hljs-keyword">include</span> <span class="hljs-keyword">file</span>=<span class="hljs-string">"user/header"</span> title=<span class="hljs-string">"查看用户列表"</span> keywords=<span class="hljs-string">"thinkphp"</span> <span class="hljs-regexp">/}</span> ``` ``` 也可以支持传递动态变量的方式,例如: ``` <pre class="calibre18"> ``` {<span class="hljs-keyword">include</span> <span class="hljs-keyword">file</span>=<span class="hljs-string">"user/header"</span> title=<span class="hljs-string">"$title"</span> <span class="hljs-regexp">/}</span> ``` ``` ## 模板定位 `fetch`方法的第一个参数表示渲染的模板文件或者模板表达式。 通常我们都是使用的模板表达式,而不需要使用完整的文件名。 模板文件名可以随意命名,如果把`index.html`文件改成: ``` <pre class="calibre18"> ``` application<span class="hljs-regexp">/index/</span>view<span class="hljs-regexp">/user/</span>list.html ``` ``` index操作方法中的fetch方法需要改成: ``` <pre class="calibre18"> ``` <span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->fetch(<span class="hljs-string">'list'</span>); ``` ``` 而如果fetch方法改成: ``` <pre class="calibre18"> ``` <span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->fetch(<span class="hljs-string">'index/list'</span>); ``` ``` 那么实际渲染的模板文件则是 ``` <pre class="calibre18"> ``` application/<span class="hljs-keyword">index</span>/view/<span class="hljs-keyword">index</span>/list.html ``` ``` 当然,你可以设置更多的目录级别,例如: ``` <pre class="calibre18"> ``` <span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->fetch(<span class="hljs-string">'one/two/three/list'</span>); ``` ``` 那么实际渲染的模板文件则是 ``` <pre class="calibre18"> ``` application<span class="hljs-regexp">/index/</span>view<span class="hljs-regexp">/one/</span>two<span class="hljs-regexp">/three/</span>list.html ``` ``` 有一些和模板定位相关的设置参数能够帮助你调整模板文件的位置和名称。 通常来说,模板相关的参数可以直接在配置文件中配置`template`参数,默认的配置如下: ``` <pre class="calibre18"> ``` <span class="hljs-string">'template'</span> => [ <span class="hljs-comment">// 模板引擎类型 支持 php think 支持扩展</span><span class="hljs-string">'type'</span> => <span class="hljs-string">'Think'</span>, <span class="hljs-comment">// 模板路径</span><span class="hljs-string">'view_path'</span> => <span class="hljs-string">''</span>, <span class="hljs-comment">// 模板后缀</span><span class="hljs-string">'view_suffix'</span> => <span class="hljs-string">'.html'</span>, <span class="hljs-comment">// 模板文件名分隔符</span><span class="hljs-string">'view_depr'</span> => DS, <span class="hljs-comment">// 模板引擎普通标签开始标记</span><span class="hljs-string">'tpl_begin'</span> => <span class="hljs-string">'{'</span>, <span class="hljs-comment">// 模板引擎普通标签结束标记</span><span class="hljs-string">'tpl_end'</span> => <span class="hljs-string">'}'</span>, <span class="hljs-comment">// 标签库标签开始标记</span><span class="hljs-string">'taglib_begin'</span> => <span class="hljs-string">'{'</span>, <span class="hljs-comment">// 标签库标签结束标记</span><span class="hljs-string">'taglib_end'</span> => <span class="hljs-string">'}'</span>, ], ``` ``` `view_path`参数决定了你的模板文件的根目录,如果没有设置的话系统会默认使用当前模块的视图目录`view`。 如果希望自定义模板文件的位置、命名和后缀,可以对模板参数稍加修改如下: ``` <pre class="calibre18"> ``` <span class="hljs-string">'template'</span> => [ <span class="hljs-comment">// 模板引擎类型 支持 php think 支持扩展</span><span class="hljs-string">'type'</span> => <span class="hljs-string">'Think'</span>, <span class="hljs-comment">// 模板路径</span><span class="hljs-string">'view_path'</span> => <span class="hljs-string">'../template/index/'</span>, <span class="hljs-comment">// 模板后缀</span><span class="hljs-string">'view_suffix'</span> => <span class="hljs-string">'.tpl'</span>, <span class="hljs-comment">// 模板文件名分隔符</span><span class="hljs-string">'view_depr'</span> => <span class="hljs-string">'_'</span>, ], ``` ``` 通过配置我们把当前渲染的模板文件移动到了 ``` <pre class="calibre18"> ``` ROOT_PATH/template/<span class="hljs-keyword">index</span>/user_index.tpl ``` ``` ## 模板布局 现在使用模板布局来进一步简化模板定义。 首先需要定义一个布局模板文件,放到 `application/index/view/layout.html`内容如下: ``` <pre class="calibre18"> ``` {<span class="hljs-keyword">include</span> file=<span class="hljs-string">"user/header"</span> /} {__CONTENT__} {<span class="hljs-keyword">include</span> file=<span class="hljs-string">"user/footer"</span> /} ``` ``` `application/index/view/user/index.html`改成: ``` <pre class="calibre18"> ``` {layout name=<span class="hljs-string">"layout"</span> /} <h2>用户列表({<span class="hljs-regexp">$count</span>})</h2> {volist name=<span class="hljs-string">"list"</span> id=<span class="hljs-string">"user"</span> } <div class=<span class="hljs-string">"info"</span>> ID:{<span class="hljs-regexp">$user</span>.id}<br/> 昵称:{<span class="hljs-regexp">$user</span>.nickname}<br/> 邮箱:{<span class="hljs-regexp">$user</span>.email}<br/> 生日:{<span class="hljs-regexp">$user</span>.birthday}<br/> </div> {/volist} ``` ``` 在index模板文件中开头定义`layout`标签 ,表示当前模板使用了布局,布局模板文件为`layout.html`,布局模板中的 `{__CONTENT__}`会自动替换为解析后的index.html内容。 如果你的布局模板中不是使用`{__CONTENT__}`的话,可以改成: ``` <pre class="calibre18"> ``` {layout name=<span class="hljs-string">"layout/newlayout"</span> <span class="hljs-number">replace</span>=<span class="hljs-string">"[__REPLACE__]"</span> /} ``` ``` 那么回自动读取模板文件 `application/index/view/layout/newlayout.html`,内容如下: ``` <pre class="calibre18"> ``` {<span class="hljs-keyword">include</span> file=<span class="hljs-string">"user/header"</span> /} [__REPLACE__] {<span class="hljs-keyword">include</span> file=<span class="hljs-string">"user/footer"</span> /} ``` ``` 如果你所有的模板文件都统一使用布局,并且都是有同一个布局模板,那么可以统一配置而不需要在模板文件中使用`layout`标签定义。 在应用配置或者模块配置中添加如下设置参数: ``` <pre class="calibre18"> ``` <span class="hljs-string">'template'</span> => [ <span class="hljs-string">'layout_on'</span> => <span class="hljs-keyword">true</span>, <span class="hljs-string">'layout_name'</span> => <span class="hljs-string">'layout'</span>, <span class="hljs-string">'layout_item'</span> => <span class="hljs-string">'[__REPLACE__]'</span> ] ``` ``` 模板文件中只需要定义如下: ``` <pre class="calibre18"> ``` <h2>用户列表({<span class="hljs-regexp">$count</span>})</h2> {volist name=<span class="hljs-string">"list"</span> id=<span class="hljs-string">"user"</span> mod=<span class="hljs-string">"2"</span> } <div class=<span class="hljs-string">"info"</span>> ID:{<span class="hljs-regexp">$user</span>.id}<br/> 昵称:{<span class="hljs-regexp">$user</span>.nickname}<br/> 邮箱:{<span class="hljs-regexp">$user</span>.email}<br/> 生日:{<span class="hljs-regexp">$user</span>.birthday}<br/> </div> {/volist} ``` ``` 访问 ``` <pre class="calibre18"> ``` <span class="hljs-string">http:</span> <span class="hljs-comment">//tp5.com/user/index</span> ``` ``` 可以看到页面输出结果和之前一样: ![](https://img.kancloud.cn/5b/14/5b1428373ea05fac9eb233d35dca4759_885x746.png) 如果想动态控制模板文件使用布局,则可以在控制器中使用: ``` <pre class="calibre18"> ``` <span class="hljs-comment">// 获取用户数据列表</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span><span class="hljs-number">()</span></span>{ <span class="hljs-regexp">$list</span> = UserModel::all(); <span class="hljs-regexp">$this</span>->assign(<span class="hljs-string">'list'</span>, <span class="hljs-regexp">$list</span>); <span class="hljs-regexp">$this</span>->assign(<span class="hljs-string">'count'</span>, count(<span class="hljs-regexp">$list</span>)); <span class="hljs-comment">// 动态使用布局</span><span class="hljs-regexp">$this</span>->view->engine->layout(<span class="hljs-string">'layout'</span>,<span class="hljs-string">'[__REPLACE__]'</span>); <span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->fetch(); } ``` ``` > 注意:这里调用的是`this->view->engine`对象的`layout`方法,并不是所有的模板引擎都支持布局功能,如果你使用的是其它的模板引擎,可能不提供`layout`方法。 如果使用配置方式开启了布局模板,也可以使用该方法临时关闭布局,例如: ``` <pre class="calibre18"> ``` <span class="hljs-comment">// 获取用户数据列表</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span><span class="hljs-number">()</span></span>{ <span class="hljs-regexp">$list</span> = UserModel::all(); <span class="hljs-regexp">$this</span>->assign(<span class="hljs-string">'list'</span>, <span class="hljs-regexp">$list</span>); <span class="hljs-regexp">$this</span>->assign(<span class="hljs-string">'count'</span>, count(<span class="hljs-regexp">$list</span>)); <span class="hljs-comment">// 临时关闭布局</span><span class="hljs-regexp">$this</span>->view->engine->layout(<span class="hljs-keyword">false</span>); <span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->fetch(); } ``` ``` 或者直接在模板文件的开头加上`{__NOLAYOUT__}`标签: ``` <pre class="calibre18"> ``` {__NOLAYOUT__} <h2>用户列表({<span class="hljs-regexp">$count</span>})</h2> {volist name=<span class="hljs-string">"list"</span> id=<span class="hljs-string">"user"</span> mod=<span class="hljs-string">"2"</span> } <div class=<span class="hljs-string">"info"</span>> ID:{<span class="hljs-regexp">$user</span>.id}<br/> 昵称:{<span class="hljs-regexp">$user</span>.nickname}<br/> 邮箱:{<span class="hljs-regexp">$user</span>.email}<br/> 生日:{<span class="hljs-regexp">$user</span>.birthday}<br/> </div> {/volist} ``` ``` ## 标签定制 可以设置模板标签的定界符: ``` <pre class="calibre18"> ``` <span class="hljs-string">'template'</span> => [ <span class="hljs-comment">// 模板引擎类型 支持 php think 支持扩展</span><span class="hljs-string">'type'</span> => <span class="hljs-string">'Think'</span>, <span class="hljs-comment">// 模板路径</span><span class="hljs-string">'view_path'</span> => <span class="hljs-string">'../template/index/'</span>, <span class="hljs-comment">// 模板后缀</span><span class="hljs-string">'view_suffix'</span> => <span class="hljs-string">'.tpl'</span>, <span class="hljs-comment">// 模板文件名分隔符</span><span class="hljs-string">'view_depr'</span> => <span class="hljs-string">'_'</span>, <span class="hljs-comment">// 模板引擎普通标签开始标记</span><span class="hljs-string">'tpl_begin'</span> => <span class="hljs-string">'{'</span>, <span class="hljs-comment">// 模板引擎普通标签结束标记</span><span class="hljs-string">'tpl_end'</span> => <span class="hljs-string">'}'</span>, <span class="hljs-comment">// 标签库标签开始标记</span><span class="hljs-string">'taglib_begin'</span> => <span class="hljs-string">'<'</span>, <span class="hljs-comment">// 标签库标签结束标记</span><span class="hljs-string">'taglib_end'</span> => <span class="hljs-string">'>'</span>, ], ``` ``` 并且修改`index.html`模板中的标签修改如下: ``` <pre class="calibre18"> ``` <span class="hljs-regexp"><<span class="hljs-operator">h2</span>></span>用户列表({$count})<span class="hljs-regexp"></<span class="hljs-operator">h2</span>></span><span class="hljs-regexp"><<span class="hljs-operator">div</span> <span class="hljs-operator">class</span>=<span class="hljs-string">"info"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">volist</span> <span class="hljs-operator">name</span>=<span class="hljs-string">"list"</span> <span class="hljs-operator">id</span>=<span class="hljs-string">"user"</span> ></span> ID:{$user.id}<span class="hljs-regexp"><<span class="hljs-operator">br</span>/></span> 昵称:{$user.nickname}<span class="hljs-regexp"><<span class="hljs-operator">br</span>/></span> 邮箱:{$user.email}<span class="hljs-regexp"><<span class="hljs-operator">br</span>/></span> 生日:{$user.birthday}<span class="hljs-regexp"><<span class="hljs-operator">br</span>/></span><span class="hljs-regexp"></<span class="hljs-operator">volist</span>></span><span class="hljs-regexp"></<span class="hljs-operator">div</span>></span> ``` ``` ## 输出替换 为了更加清晰,需要把资源文件独立出来,并在模板文件中引入,例如增加`public/static/common.css`文件: ``` <pre class="calibre18"> ``` <span class="hljs-regexp">body</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#333</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">font</span>:<span class="hljs-string"> <span class="hljs-number">16px</span> Verdana, <span class="hljs-operator">"Helvetica Neue"</span>, helvetica, Arial, <span class="hljs-operator">'Microsoft YaHei'</span>, sans-serif</span></span>; <span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"> <span class="hljs-number">0px</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">20px</span></span></span>; }</span><span class="hljs-regexp">a</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#868686</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">cursor</span>:<span class="hljs-string"> pointer</span></span>; }</span><span class="hljs-operator"><span class="hljs-title1">a</span>:<span class="hljs-string">hover{ text-decoration: underline</span></span>; } <span class="hljs-regexp">h2</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">color</span>:<span class="hljs-string"> <span class="hljs-title">#4288ce</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">font-weight</span>:<span class="hljs-string"> <span class="hljs-number">400</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">6px</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"> <span class="hljs-number">6px</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">font-size</span>:<span class="hljs-string"> <span class="hljs-number">28px</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">border-bottom</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>; }</span><span class="hljs-regexp">div</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">margin</span>:<span class="hljs-string"><span class="hljs-number">8px</span></span></span>; }</span><span class="hljs-regexp">.info</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">12px</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">border-bottom</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>; }</span><span class="hljs-regexp">.copyright</span><span class="hljs-operator">{ <span class="hljs-operator"><span class="hljs-title1">margin-top</span>:<span class="hljs-string"> <span class="hljs-number">24px</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">padding</span>:<span class="hljs-string"> <span class="hljs-number">12px</span> <span class="hljs-number">0</span></span></span>; <span class="hljs-operator"><span class="hljs-title1">border-top</span>:<span class="hljs-string"> <span class="hljs-number">1px</span> solid <span class="hljs-title">#eee</span></span></span>; }</span> ``` ``` 我们在header.html文件中引入资源文件 ``` <pre class="calibre18"> ``` <span class="hljs-regexp"><<span class="hljs-operator">html</span>></span><span class="hljs-regexp"><<span class="hljs-operator">head</span>></span><span class="hljs-regexp"><<span class="hljs-operator">meta</span> <span class="hljs-operator">charset</span>=<span class="hljs-string">"UTF-8"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">title</span>></span>[title]<span class="hljs-regexp"></<span class="hljs-operator">title</span>></span><span class="hljs-regexp"><<span class="hljs-operator">link</span> <span class="hljs-operator">charset</span>=<span class="hljs-string">"utf-8"</span> <span class="hljs-operator">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-operator">href</span>=<span class="hljs-string">"/static/common.css"</span>></span><span class="hljs-regexp"></<span class="hljs-operator">head</span>></span><span class="hljs-regexp"><<span class="hljs-operator">body</span>></span> ``` ``` 但这样有一个问题,如果部署的目录变化的话,资源文件的路径就会跟着变化,这里我们采用输出替换功能,使得资源文件的引入动态化 可以在输出之前对解析后的内容进行替换,使用: ``` <pre class="calibre18"> ``` <span class="hljs-comment">// 读取用户数据</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-number">(<span class="hljs-regexp">$id</span>=<span class="hljs-string">''</span>)</span></span>{ <span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-regexp">$id</span>); <span class="hljs-regexp">$this</span>->assign(<span class="hljs-string">'user'</span>,<span class="hljs-regexp">$user</span>); <span class="hljs-regexp">$this</span>->view->replace([ <span class="hljs-string">'__PUBLIC__'</span> => <span class="hljs-string">'/static'</span>, ]); <span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->fetch(); } ``` ``` 模板文件改为: ``` <pre class="calibre18"> ``` <span class="hljs-regexp"><<span class="hljs-operator">html</span>></span><span class="hljs-regexp"><<span class="hljs-operator">head</span>></span><span class="hljs-regexp"><<span class="hljs-operator">meta</span> <span class="hljs-operator">charset</span>=<span class="hljs-string">"UTF-8"</span>></span><span class="hljs-regexp"><<span class="hljs-operator">title</span>></span>[title]<span class="hljs-regexp"></<span class="hljs-operator">title</span>></span><span class="hljs-regexp"><<span class="hljs-operator">link</span> <span class="hljs-operator">charset</span>=<span class="hljs-string">"utf-8"</span> <span class="hljs-operator">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-operator">href</span>=<span class="hljs-string">"__PUBLIC__/common.css"</span>></span><span class="hljs-regexp"></<span class="hljs-operator">head</span>></span><span class="hljs-regexp"><<span class="hljs-operator">body</span>></span> ``` ``` 最终输出的时候,会自动进行`__PUBLIC__`替换。 ## 渲染内容 有时候,并不需要模板文件,而是直接渲染内容或者读取数据库中存储的内容,控制器方法修改如下: ``` <pre class="calibre18"> ``` <span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">controller</span>; <span class="hljs-keyword">use</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>\<span class="hljs-title">User</span> <span class="hljs-title">as</span> <span class="hljs-title">UserModel</span>; <span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Controller</span>; <span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Controller</span></span>{ <span class="hljs-comment">// 获取用户数据列表并输出</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span><span class="hljs-number">()</span></span>{ <span class="hljs-regexp">$list</span> = UserModel::all(); <span class="hljs-regexp">$this</span>->assign(<span class="hljs-string">'list'</span>, <span class="hljs-regexp">$list</span>); <span class="hljs-regexp">$this</span>->assign(<span class="hljs-string">'count'</span>, count(<span class="hljs-regexp">$list</span>)); <span class="hljs-comment">// 关闭布局 </span><span class="hljs-regexp">$this</span>->view->engine->layout(<span class="hljs-keyword">false</span>); <span class="hljs-regexp">$content</span> = <span class="hljs-string"><<<EOT <style> body{ color: #333; font: 16px Verdana, "Helvetica Neue", helvetica, Arial, 'Microsoft YaHei', sans-serif; margin: 0px; padding: 20px; } a{ color: #868686; cursor: pointer; } a:hover{ text-decoration: underline; } h2{ color: #4288ce; font-weight: 400; padding: 6px 0; margin: 6px 0 0; font-size: 28px; border-bottom: 1px solid #eee; } div{ margin:8px; } .info{ padding: 12px 0; border-bottom: 1px solid #eee; } .copyright{ margin-top: 24px; padding: 12px 0; border-top: 1px solid #eee; } </style> <h2>用户列表({\$count})</h2> <div> {volist name="list" id="user" } ID:{\$user.id}<br/> 昵称:{\$user.nickname}<br/> 邮箱:{\$user.email}<br/> 生日:{\$user.birthday}<br/> ------------------------<br/> {/volist} </div> <div class="copyright"> <a title="官方网站" href="http://www.thinkphp.cn">ThinkPHP</a> <span>V5</span> <span>{ 十年磨一剑-为API开发设计的高性能框架 }</span> </div> EOT;</span><span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->display(<span class="hljs-regexp">$content</span>); } }</span> ``` ``` `display`方法用于渲染内容而不是模板文件输出,和直接使用`echo`输出的区别是`display`方法输出的内容支持模板标签的解析。 ## 助手函数 可以使用系统提供的助手函数view简化模板渲染输出(注意不适用于内容渲染输出): 前面的模板渲染代码可以改为: ``` <pre class="calibre18"> ``` <span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">controller</span>; <span class="hljs-keyword">use</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>\<span class="hljs-title">User</span> <span class="hljs-title">as</span> <span class="hljs-title">UserModel</span>; <span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span></span>{ <span class="hljs-comment">// 读取用户数据</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-number">(<span class="hljs-regexp">$id</span>=<span class="hljs-string">''</span>)</span></span>{ <span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-regexp">$id</span>); <span class="hljs-keyword">return</span> view(<span class="hljs-string">''</span>, [<span class="hljs-string">'user'</span> => <span class="hljs-regexp">$user</span>], [<span class="hljs-string">'__PUBLIC__'</span> => <span class="hljs-string">'/static'</span>]); } }</span> ``` ``` > 使用`view`助手函数,不需要继承`think\Controller`类。该方法的第一个参数就是渲染的模板表达式。