ThinkPHP8学习篇(十四):模板

在 ThinkPHP 的模板引擎中,标签系统提供了简洁而强大的语法,使开发者能够以更直观的方式处理视图逻辑与数据展示。合理使用模板标签不仅能提升开发效率,还能保持模板代码的整洁性与可读性。本文将系统学习模板引擎中常用的标签用法,包括变量输出、模板运算符的使用技巧、注释的规范写法、文件包含的方式以及条件判断、循环遍历等内置标签的应用。通过掌握这些核心标签,能够快速完成大部分模板开发需求。

模板

一、变量输出

1、使用默认值

2、系统变量输出

二、使用函数

三、运算符

1、三元运算符

四、模板注释

1、单行注释

2、多行注释

五、模板布局

1、全局配置方式

2、模板标签方式

3、动态方法布局

六、模板继承

七、包含文件

1、使用模版表达式

2、使用模版文件

3、传入参数

八、标签库

1、导入标签库

2、内置标签

3、标签库预加载

九、内置标签

1、循环标签

[1.1、foreach 标签](#1.1、foreach 标签)

[1.2、volist 标签](#1.2、volist 标签)

[1.3、for 标签](#1.3、for 标签)

2、比较标签

3、条件判断

[3.1、switch 标签](#3.1、switch 标签)

[3.2、if 标签](#3.2、if 标签)

4、资源文件

[5、原生 PHP](#5、原生 PHP)

[5.1、使用 php 标签](#5.1、使用 php 标签)

5.2、使用原生PHP代码

6、定义标签

[6.1、assign 标签](#6.1、assign 标签)

[6.2、define 标签](#6.2、define 标签)


模板

ThinkTemplate 是一个基于XML的性能卓越的编译型模板引擎,支持两种类型的模板标签,使用了动态编译和缓存技术,而且支持自定义标签库,一直作为 ThinkPHP 的内置模板引擎,现已经支持独立使用。

主要特性:

  • 支持模板标签定界符定义;
  • 支持直接使用PHP代码书写;
  • 支持文件包含;
  • 支持多级标签嵌套;
  • 支持布局模板功能;
  • 一次编译多次运行,编译和运行效率非常高;
  • 模板文件和布局模板更新,自动更新模板缓存;
  • 系统变量无需赋值直接输出;
  • 支持多维数组的快速输出;
  • 支持模板变量的默认值;
  • 支持页面代码去除Html空白;
  • 支持变量组合调节器和格式化功能;
  • 允许定义模板禁用函数和禁用PHP语法;
  • 通过标签库方式扩展。

模板引擎支持普通标签和XML标签方式两种标签定义,分别用于不同的目的:

  • 普通标签:主要用于输出变量、函数过滤和做一些基本的运算操作。
  • 标签库标签:主要完成一些逻辑判断、控制和循环输出,并且可扩展。

模板文件可以同时包含普通标签和标签库标签,标签的定界符都可以重新配置。

普通标签用于变量输出和模板注释,普通模板标签默认以 { 和 } 作为开始和结束标识,并且在开始标记紧跟标签的定义,如果之间有空格或者换行则被视为非模板标签直接输出。 例如:{name} 、{vo.name} 、{vo\['name'\]\|strtoupper} 都属于正确的标签,而 { name} 、{ $vo.name} 则不属于。

要更改普通标签的起始标签和结束标签,可以更改 config\view.php 中的配置参数:

php 复制代码
// 普通标签开始标记 
'tpl_begin' =>    '<{',
// 普通标签结束标记
'tpl_end'   =>    '}>'

普通标签的定界符就被修改了,原来的 {name} 和 {vo.name} 必须使用 <{name}\> 和 \<{vo.name}> 才能生效。

标签库标签可以用于模板变量输出、文件包含、条件控制、循环输出等功能,而且完全可以自己扩展功能。

最新版本的标签库默认定界符和普通标签一样使用 { 和 },是为了便于在编辑器里面编辑不至于报错。当然,仍然可以更改标签库标签的起始和结束标签(配置文件为:config\view.php),修改下面的配置参数:

php 复制代码
//标签库标签开始标签 
'taglib_begin'  =>  '<',
//标签库标签结束标记
'taglib_end'    =>  '>',

一、变量输出

在模板中输出变量的方法很简单,例如,在控制器的方法中我们给模板变量赋值:

php 复制代码
return View::fetch('index', ['name' => 'Test']);

在 index.html 模板文件中使用 {} 取值:

php 复制代码
Hello,{$name}!

模板编译后的结果就是:

php 复制代码
Hello,<?php echo htmlentities($name);?>!

运行的时候就会在模板中显示:Hello,Test!

注意模板标签的 { 和 $ 之间不能有任何的空格,否则标签无效。所以,下面的标签

php 复制代码
Hello,{ $name}!

将不会正常输出name变量,而是直接保持不变输出:Hello,{ $name}!

模板标签的变量输出根据变量类型有所区别,刚才我们输出的是字符串变量,如果是数组变量:

php 复制代码
$data['name'] = 'zhangsan';
$data['email'] = 'test@test.com';
return View::fetch('hello', ['data' => $data]);

在模板中用下面的方式输出:

html 复制代码
Name:{$data.name}
<br/>
Email:{$data.email}

或者用下面的方式也是一样的:

html 复制代码
Name:{$data['name']}
<br/>
Email:{$data['email']}

也可以直接调用对象的常量或者方法

html 复制代码
常量:{$data::CONST_NAME}
方法:{$data->fun()}

1、使用默认值

可以给变量输出提供默认值,例如:

html 复制代码
{$data.nickname|default="默认值"}

使用 |default 的方式为变量输出提供默认值。

2、系统变量输出

普通的模板变量需要首先赋值后才能在模板中输出,但是系统变量则不需要,可以直接在模板中输出。系统变量的输出通常以 {$Request.(大小写一致) 打头,例如:

html 复制代码
{$Request.server.script_name} // 输出$_SERVER['SCRIPT_NAME']变量
{$Request.session.user_id} // 输出$_SESSION['user_id']变量
{$Request.get.page} // 输出$_GET['page']变量
{$Request.cookie.name}  // 输出$_COOKIE['name']变量

支持输出 _SERVER、_ENV、_POST、_GET、_REQUEST、_SESSION 和 $_COOKIE 变量。

二、使用函数

使用 |函数名称 的方式可以使用函数进行过滤或其它处理。例如:

html 复制代码
{$data.name|md5}
<!-- 可以使用空格,下面的写法是一样的: -->
{$data.name | md5} 

编译后的结果是:

php 复制代码
<?php echo htmlentities(md5($data['name'])); ?>

其中 htmlentities 方法是系统默认添加的,无需手动指定。

为了避免出现XSS安全问题,默认的变量输出都会使用 htmlentities 方法进行转义输出。

如果不需要转义(例如需要输出html表格等内容),可以使用 |raw:

html 复制代码
{$data.name|raw}

编译后的结果是:

php 复制代码
<?php echo $data['name']; ?>

系统内置了下面几个固定的过滤规则(不区分大小写)

|----------|-----------------|
| 过滤方法 | 描述 |
| date | 日期格式化(支持各种时间类型) |
| format | 字符串格式化 |
| upper | 转换为大写 |
| lower | 转换为小写 |
| first | 输出数组的第一个元素 |
| last | 输出数组的最后一个元素 |
| default | 默认值 |
| raw | 不使用(默认)转义 |

例如

html 复制代码
{$data.create_time|date='Y-m-d H:i'}
{$data.number|format='%02d'}

如果函数有多个参数需要调用,可以使用

html 复制代码
{$data.name|substr=0,3}

表示输出

php 复制代码
<?php echo htmlentities(substr($data['name'],0,3)); ?>

还可以支持多个函数过滤,多个函数之间用"|"分割即可,例如:

html 复制代码
{$data.name|md5|upper|substr=0,3}

编译后的结果是:

php 复制代码
<?php echo htmlentities(substr(strtoupper(md5($name)),0,3)); ?>

函数会按照从左到右的顺序依次调用(系统默认的过滤规则会在最后调用)。

三、运算符

我们可以对模板输出使用运算符,包括:

|---------|----------------|
| 运算符 | 使用示例 |
| + | {a+b} |
| - | {a-b} |
| * | {a\*b} |
| / | {a/b} |
| % | {a%b} |
| ++ | {a++}或{++a} |
| -- | {a--}或{--a} |
| 综合运算 | {a+b*10+$c} |

在使用运算符的时候,不再支持前面提到的函数过滤用法,例如:

html 复制代码
{$data.score+10} //正确的
{$data['score']+10} //正确的
{$data['score']*$data['level']} //正确的
{$data['score']|myFun*10} //错误的
{$data['score']+myFun($data['level'])} //正确的

1、三元运算符

模板可以支持三元运算符,例如:

html 复制代码
{$status? '正常' : '错误'}

还支持如下的写法:

html 复制代码
{$name ?? '默认值'}

表示如果设置 name 则输出 name,否则输出默认值。

四、模板注释

1、单行注释

格式:

html 复制代码
{// 注释内容 }

注意 :{ 和注释标记之间不能有空格。

2、多行注释

格式:

html 复制代码
{/* 这是模板
注释内容*/ }

模板注释支持多行。模板注释在生成编译缓存文件后会自动删除,这一点和Html的注释不同。

五、模板布局

ThinkPHP 的模板引擎内置了布局模板功能支持,可以方便的实现模板布局以及布局嵌套功能。共有三种布局模板的支持方式。

1、全局配置方式

这种方式仅需在项目配置文件(config\view.php)中添加相关的布局模板配置,就可以简单实现模板布局功能,比较适用于全站使用相同布局的情况,需要配置开启 layout_on 参数(默认不开启),并且设置布局入口文件名 layout_name (默认为layout)。

php 复制代码
return  [
    'layout_on'     =>  true,
    'layout_name'   =>  'layout',
]

开启 layout_on 后,我们的模板渲染流程就有所变化,例如:

php 复制代码
<?php
namespace app\controller;

use app\BaseController;
use think\facade\View;

class Index extends BaseController
{
    public function index()
    {
        return View::fetch('index');
    }
}

在不开启 layout_on 布局模板之前,会直接渲染 view/index/index.html 模板文件,开启之后,首先会渲染 view/layout.html 模板,布局模板的写法和其他模板的写法类似,本身也可以支持所有的模板标签以及包含文件,区别在于有一个特定的输出替换变量 {CONTENT},例如,下面是一个典型的 layout.html 模板的写法:

html 复制代码
{include file="public/header" /}
 {__CONTENT__}
{include file="public/footer" /}

读取layout模板之后,会再解析 index/index.html 模板文件,并把解析后的内容替换到layout布局模板文件的 {CONTENT} 特定字符串。

当然也可以通过设置来改变这个特定的替换字符串,例如:

php 复制代码
return [
    'layout_on'     =>  true,
    'layout_name'   =>  'layout',
    'layout_item'   =>  '{__REPLACE__}'
]

一个布局模板同时只能有一个特定替换字符串。

采用这种布局方式的情况下,一旦 index/index.html 模板文件或者 layout.html 布局模板文件发生修改,都会导致模板重新编译。

如果需要指定其他位置的布局模板,可以指定 layout_name:

php 复制代码
return [
    'layout_on'     =>  true,
    'layout_name'   =>  'layout/layoutname',
    'layout_item'   =>  '{__REPLACE__}'
]

表示采用 view/layout/layoutname.html 作为布局模板。

如果某些页面不需要使用布局模板功能,可以在模板文件开头加上 {NOLAYOUT} 字符串。

如果上面的 index/index.html 模板文件里面包含有 {NOLAYOUT},则即使当前开启布局模板,也不会进行布局模板解析。

2、模板标签方式

这种布局模板不需要在配置文件中设置任何参数,也不需要开启 layout_on,直接在模板文件中指定布局模板即可,相关的布局模板调整也在模板中进行。

以前面的输出模板为例,这种方式的入口还是在 index/index.html 模板,但是我们可以修改下 index 模板文件的内容,在头部增加下面的布局标签(记得首先关闭前面的 layout_on 设置,否则可能出现布局循环):

html 复制代码
{layout name="layout" /}

表示当前模板文件需要使用 layout.html 布局模板文件,而布局模板文件的写法和上面第一种方式是一样的。当渲染 index/index.html 模板文件的时候,如果读取到 layout 标签,则会把当前模板的解析内容替换到 layout 布局模板的 {CONTENT} 特定字符串。

一个模板文件中只能使用一个布局模板,如果模板文件中没有使用任何 layout 标签则表示当前模板不使用任何布局。

如果需要使用其它的布局模板,可以改变 layout 的 name 属性,例如:

html 复制代码
{layout name="newlayout" /}

还可以在 layout 标签里面使用 replace 属性指定要替换的特定字符串:

html 复制代码
{layout name="Layout/newlayout" replace="[__REPLACE__]" /}

3、动态方法布局

使用内置的 layout 方法可以灵活的在程序中控制模板输出的布局功能,尤其适用于局部需要布局或者关闭布局的情况,这种方式也不需要在配置文件中开启 layout_on。例如:

php 复制代码
<?php
namespace app\controller;

use app\BaseController;
use think\facade\View;

class Index extends BaseController
{
    public function index()
    {
        View::engine()->layout(true);
        return View::fetch('index');
    }
}

表示当前的模板输出启用了布局模板,并且采用默认的 layout 布局模板。

如果当前输出需要使用不同的布局模板,可以在 layout 方法中动态的指定布局模板名称,例如:

php 复制代码
<?php
namespace app\controller;

use app\BaseController;
use think\facade\View;

class Index extends BaseController
{
    public function index()
    {
        View::engine()->layout('Layout/newlayout');
        return View::fetch('index');
    }
}

使用 layout 方法可以动态关闭当前模板的布局功能(这种用法可以配合第一种布局方式,例如全局配置已经开启了布局,可以在某个页面单独关闭):

php 复制代码
<?php
namespace app\controller;

use app\BaseController;
use think\facade\View;

class Index extends BaseController
{
    public function index()
    {
        // 临时关闭当前模板的布局功能
        View::engine()->layout(false);
        return View::fetch('index');
    }
}

三种模板布局方式中,第一种和第三种是在程序中配置实现模板布局,第二种方式则是单纯通过模板标签在模板中使用布局。具体选择什么方式,需要根据项目的实际情况来定。

六、模板继承

模板继承是一种更加灵活的模板布局方式,模板继承不同于模板布局,甚至来说,应该在模板布局的上层。模板继承其实并不难理解,就好比类的继承一样,模板也可以定义一个基础模板(或者是布局),并且其中定义相关的区块(block),然后继承(extend)该基础模板的子模板中就可以对基础模板中定义的区块进行重载。

因此,模板继承的优势其实是设计基础模板中的区块(block)和子模板中替换这些区块。每个区块由 {block} {/block} 标签组成。 下面就是基础模板中的一个典型的区块设计(用于设计网站标题):

html 复制代码
{block name="title"}<title>网站标题</title>{/block}

block 标签必须指定 name 属性来标识当前区块的名称,这个标识在当前模板中是唯一的,block 标签中可以包含任何模板内容,包括其他标签和变量,例如:

html 复制代码
{block name="title"}<title>{$web_title}</title>{/block}

甚至还可以在区块中加载外部文件:

html 复制代码
{block name="include"}{include file="Public:header" /}{/block}

一个模板中可以定义任意多个名称标识不重复的区块 。例如下面定义了一个 base.html 基础模板:

html 复制代码
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>{block name="title"}标题{/block}</title>
</head>
<body>
{block name="menu"}菜单{/block}
{block name="left"}左边分栏{/block}
{block name="main"}主内容{/block}
{block name="right"}右边分栏{/block}
{block name="footer"}底部{/block}
</body>
</html>

然后我们在子模板中使用继承:

html 复制代码
{extend name="base" /}

{block name="title"}{$title}{/block}

{block name="menu"}
<a href="/" >首页</a>
<a href="/info/" >资讯</a>
<a href="/bbs/" >论坛</a>
{/block}

{block name="left"}{/block}

{block name="main"}
{volist name="list" id="vo"}
<a href="/new/{$vo.id}">{$vo.title}</a><br/>
 {$vo.content}
{/volist}
{/block}

{block name="right"}
 最新资讯:
{volist name="news" id="new"}
<a href="/new/{$new.id}">{$new.title}</a><br/>
{/volist}
{/block}

{block name="footer"}
{__block__}
 @版权所有
{/block}

上述示例中,可以看到在子模板中使用了 extend 标签来继承了 base 模板。

在子模板中,可以对基础模板中的区块进行重载定义,如果没有重新定义的话,则表示沿用基础模板中的区块定义,如果定义了一个空的区块,则表示删除基础模板中的该区块内容。 上面的例子,我们就把left区块的内容删除了,其他的区块都进行了重载。而

html 复制代码
{block name="footer"}
{__block__}
@版权所有
{/block}

这一区块中有 {block} 这个标签,当区块中有这个标记时,就不只是直接重载这个区块。它表示引用所继承模板对应区块的内容到这个位置,最终这个区块是合并后的内容。所以这里footer区块最后的内容是:底部 @版权所有。

extend 标签也可以加载其它模板:

html 复制代码
{extend name="Public:base" /}

或者使用绝对文件路径加载

html 复制代码
{extend name="./Template/Public/base.html" /}

在当前子模板中,只能定义区块而不能定义其他的模板内容 ,否则将会直接忽略,并且只能定义基础模板中已经定义的区块

模板可以多级继承,比如B继承了A,而C又继承了B,最终C中的区块会覆盖B和A中的同名区块,但C和B中的区块必须是A中已定义过的。子模板中的区块定义顺序是随意的,模板继承的用法关键在于基础模板如何布局和设计规划。

七、包含文件

在当前模版文件中包含其它的模版文件使用 include 标签,标签用法:

html 复制代码
{include file='模版文件1,模版文件2,...' /}

包含的模板文件中不能再使用模板布局或者模板继承。

1、使用模版表达式

模版表达式的定义规则为:模块@控制器/操作

示例

html 复制代码
{include file="public/header" /} // 包含头部模版header
{include file="public/menu" /} // 包含菜单模版menu
{include file="blue/public/menu" /} // 包含blue主题下面的menu模版

可以一次包含多个模版,例如:

html 复制代码
{include file="public/header,public/menu" /}

注意:包含模版文件并不会自动调用控制器的方法,也就是说包含的其它模版文件中的变量赋值需要在当前操作中完成。

2、使用模版文件

可以直接包含一个模版文件名(包含完整路径),例如:

html 复制代码
{include file="../view/default/public/header.html" /}

路径以项目目录 /public/ 路径为起点。

3、传入参数

include 标签支持在包含文件的同时传入参数。例如,下面的例子在包含 header 模板的时候传入了 title 和 keywords 参数:

html 复制代码
{include file="Public/header" title="$title" keywords="开源WEB开发框架" /}

就可以在包含的 header.html 文件里面使用 title 和 keywords 变量,如下:

php 复制代码
<head>
<title>[title]</title>
<meta name="keywords" content="[keywords]" />
</head>

注意 :包含文件中可以再使用 include 标签包含别的文件,但注意不要形成A包含A,或者A包含B而B又包含A这样的死循环。

八、标签库

内置的模板引擎除了支持普通变量的输出之外,更强大的地方在于标签库功能。

标签库类似于Java的JSP标签库,每一个标签库是一个独立的标签库文件,标签库中的每一个标签完成某个功能,采用XML标签方式(包括开放标签和闭合标签)。标签库分为内置和扩展标签库,内置标签库是 Cx 标签库。

1、导入标签库

使用 taglib 标签导入当前模板中需要使用的标签库,例如:

html 复制代码
{taglib name="html" /}

如果没有定义html标签库的话,则导入无效。也可以导入多个标签库

html 复制代码
{taglib name="html,article" /}

导入标签库后,就可以使用标签库中定义的标签了。假设article标签库中定义了read标签:

html 复制代码
{article:read name="hello" id="data" }
{$data.id}:{$data.title}
{/article:read}

在上面的标签中,{article:read}... {/article:read} 就是闭合标签,起始和结束标签必须成对出现。

如果是 {article:read name="hello" /} 就是开放标签。

2、内置标签

内置标签库无需导入即可使用,并且不需要加XML中的标签库前缀,ThinkPHP内置的标签库是 Cx 标签库,所以,Cx 标签库中的所有标签,可以在模板文件中直接使用:

html 复制代码
{eq name="status" value="1" }
正常
{/eq}

内置标签库可以简化模板中标签的使用,所以,还可以把其它的标签库定义为内置标签库(前提是多个标签库没有标签冲突的情况),例如:

html 复制代码
// 配置文件:config/view.php
'taglib_build_in'    =>    'cx,article'

3、标签库预加载

标签库预加载是指无需手动在模板文件中导入标签库即可使用标签库中的标签,通常用于某个标签库需要被大多数模板使用的情况。

在配置文件中添加需要预加载的标签库:

php 复制代码
'taglib_pre_load'    =>    'article,html'

设置后,模板文件就不再需要使用

html 复制代码
{taglib name="html,article" /}

九、内置标签

变量输出使用普通标签就足够了,但是要完成其他的控制、循环和判断功能,就需要借助模板引擎的标签库功能了,系统内置标签库的所有标签无需引入标签库即可直接使用。

内置标签主要包括:

|------------|------------------------------------------|-------------------------------|
| 标签名 | 作用 | 包含属性 |
| include | 包含外部模板文件(闭合) | file |
| load | 导入资源文件(闭合 包括js css import别名) | file,href,type,value,basepath |
| volist | 循环数组数据输出 | name,id,offset,length,key,mod |
| foreach | 数组或对象遍历输出 | name,item,key |
| for | For循环数据输出 | name,from,to,before,step |
| switch | 分支判断输出 | name |
| case | 分支判断输出(必须和switch配套使用) | value,break |
| default | 默认情况输出(闭合 必须和switch配套使用) | 无 |
| compare | 比较输出(包括eq neq lt gt egt elt heq nheq等别名) | name,value,type |
| range | 范围判断输出(包括in notin between notbetween别名) | name,value,type |
| present | 判断是否赋值 | name |
| notpresent | 判断是否尚未赋值 | name |
| empty | 判断数据是否为空 | name |
| notempty | 判断数据是否不为空 | name |
| defined | 判断常量是否定义 | name |
| notdefined | 判断常量是否未定义 | name |
| define | 常量定义(闭合) | name,value |
| assign | 变量赋值(闭合) | name,value |
| if | 条件判断输出 | condition |
| elseif | 条件判断输出(闭合 必须和if标签配套使用) | condition |
| else | 条件不成立输出(闭合 可用于其他标签) | 无 |
| php | 使用php代码 | 无 |

这里将挑选几个常用的标签进行说明。

1、循环标签

1.1、foreach 标签

foreach 标签的用法和PHP语法非常接近,用于循环输出数组或者对象的属性,用法如下:

php 复制代码
$list = [
    ['id' => 1, 'name' => 'zhangsan'],
    ['id' => 2, 'name' => 'lisi']
];
View::assign('list', $list);

模板文件中这样输出

html 复制代码
{foreach $list as $key=>$vo } 
    {$vo.id}:{$vo.name}
{/foreach}

1.2、volist 标签

volist 标签通常用于查询数据集或者二维数组的结果输出。 在控制器中首先对模版赋值,赋值采用和 foreach 中同样的代码。

模版定义如下,循环输出用户的编号和姓名:

html 复制代码
{volist name="list" id="vo"}
    {$vo.id}:{$vo.name}<br/>
{/volist}

volist 标签的 name 属性表示模板赋值的变量名称,因此不可随意在模板文件中改变。id 表示当前的循环变量,可以随意指定,但确保不要和 name 属性冲突,例如:

html 复制代码
{volist name="list" id="data"}
    {$data.id}:{$data.name}<br/>
{/volist}

支持输出查询结果中的部分数据,例如输出其中的第5~15条记录

html 复制代码
{volist name="list" id="vo" offset="5" length='10'}
    {$vo.name}
{/volist}

输出偶数记录

html 复制代码
{volist name="list" id="vo" mod="2" }
    {eq name="mod" value="1"}{$vo.name}{/eq}
{/volist}

mod 属性还用于控制一定记录的换行,例如:

html 复制代码
<!-- 每5条数据换行 -->
{volist name="list" id="vo" mod="5" }
    {$vo.name}
    {eq name="mod" value="4"}<br/>{/eq}
{/volist}

为空的时候输出提示:

html 复制代码
{volist name="list" id="vo" empty="暂时没有数据" }
    {$vo.id}:{$vo.name}
{/volist}

empty 属性不支持直接传入html语法,但可以支持变量输出,例如:

php 复制代码
View::assign('empty', '<b>没有数据</b>');
View::assign('list', $list);

然后在模板中使用:

html 复制代码
{volist name="list" id="vo" empty="$empty" }
    {$vo.id}:{$vo.name}
{/volist}

输出循环变量:

html 复制代码
{volist name="list" id="vo" key="k" }
    {$k}.{$vo.name}
{/volist}

如果没有指定 key 属性的话,默认使用循环变量为 i,例如:

html 复制代码
{volist name="list" id="vo"  }
    {$i}.{$vo.name}
{/volist}

如果要输出数组的索引,可以直接使用 key 变量,和循环变量不同的是,这个 key 是由数据本身决定,而不是循环控制的。例如:

html 复制代码
{volist name="list" id="vo"  }
    {$key}.{$vo.name}
{/volist}

1.3、for 标签

用法:

html 复制代码
{for start="开始值" end="结束值" comparison="循环终止条件的比较运算符" step="步进值" name="循环变量名" }
{/for}

开始值、结束值、步进值和循环变量都可以支持变量,开始值和结束值是必须其它都是可选 。comparison 的默认值是 lt(小于),name 的默认值是 i,步进值的默认值是1。

comparison 属性支持预设的运算符别名(对应 PHP 原生运算符),常用值如下:

|------------------|--------------|--------|----------------------------|
| comparison 值 | 对应PHP运算符 | 含义 | 循环终止条件 |
| lt(默认) | < | 小于 | 循环变量 >= end 时停止 |
| elt | <= | 小于等于 | 循环变量 > end 时停止(实际循环到 end) |
| gt | > | 大于 | 循环变量 |
| egt | >= | 大于等于 | 循环变量 < end 时停止(实际循环到 end) |

示例

html 复制代码
{for start="1" end="5"}
{$i} <!-- 循环条件 i<5,输出:1 2 3 4 -->
{/for}

{for start="5" end="1" comparison="egt" step="-1"}
{$i} <!-- 循环条件 i>=1,$i-=1,输出:5 4 3 2 1 -->
{/for}

2、比较标签

比较标签用于简单的变量比较,复杂的判断条件可以用 if 标签替换,比较标签是一组标签的集合,基本上用法都一致,用法如下:

html 复制代码
{比较标签 name="变量" value="值"}
内容
{/比较标签}

系统支持的比较标签以及所表示的含义分别是:

|-----------------|--------|
| 标签 | 含义 |
| eq 或者 equal | 等于 |
| neq 或者 notequal | 不等于 |
| gt | 大于 |
| egt | 大于等于 |
| lt | 小于 |
| elt | 小于等于 |
| heq | 恒等于 |
| nheq | 不恒等于 |

它们的用法基本是一致的,区别在于判断的条件不同,并且所有的比较标签都可以和 else 标签一起使用。

例如,要求 name 变量的值等于 value 就输出,可以使用:

html 复制代码
{eq name="name" value="value"}value{/eq}
<!-- 或者 -->
{equal name="name" value="value"}value{/equal}

也可以支持和 else 标签混合使用:

html 复制代码
{eq name="name" value="value"}
相等
{else/}
不相等
{/eq}

当 name 变量的值大于 10 就输出

html 复制代码
{gt name="name" value="10"}value{/gt}

还可以支持对变量使用函数 当 name 变量的值字符串长度等于 5 就输出

html 复制代码
{eq name="name|strlen" value="5"}{$name}{/eq}

通常比较标签的值是一个字符串或者数字,如果需要使用变量,只需要在前面添加 "" 标志: 当 vo 对象的属性等于 a 就输出

html 复制代码
{eq name="vo['name']" value="$a"}{$vo['name']}{/eq}

所有的比较标签可以统一使用 compare 标签(其实所有的比较标签都是 compare 标签的别名),例如: 当 name 变量的值等于 5 就输出

html 复制代码
{compare name="name" value="5" type="eq"}value{/compare}
<!-- 等效于 -->
{eq name="name" value="5" }value{/eq}

其中 type 属性的值就是上面列出的比较标签名称。

3、条件判断

3.1、switch 标签

用法:

html 复制代码
{switch 变量 }
    {case value1}输出内容1{/case}
    {case value2}输出内容2{/case}
    {default/}默认情况
{/switch}

示例

html 复制代码
{switch level}
    {case 1}一级{/case}
    {case 2}二级{/case}
    {default/}未定级
{/switch}

可以使用函数以及系统变量,例如:

html 复制代码
{switch value|strtoupper} <!-- 将 value 的值转换为大写 -->
    {case A}A{/case}
    {case B}B{/case}
    {default/}未定义
{/switch}

对于 case 属性可以支持多个条件的判断,使用"|"进行分割,例如:

html 复制代码
{switch type}
    {case gif|png|jpg}图像格式{/case}
    {default/}其它格式
{/switch}

也可以对 case 的 value 属性使用变量,例如:

html 复制代码
{switch $roleId}
    {case $adminId}admin{/case}
    {case $memberId}member{/case}
{/switch}

注意:使用变量方式的情况下,不再支持 | 分割的多个条件判断用法。

3.2、if 标签

用法:

html 复制代码
{if 表达式}value1
{elseif 表达式/}value2
{else/}value3
{/if}

示例

html 复制代码
{if $score>=90} 优秀
{elseif $score>=80} 良好
{elseif $score>=70} 中等
{elseif $score>=60} 及格
{else/} 不及格
{/if}

也可以在该标签内使用php代码,例如:

html 复制代码
{if strpos($name, 'A') === 0} 名称以A开头
{else/} 名称不以A开头
{/if}

4、资源文件

传统方式的导入外部 JS 和 CSS 文件的方法是直接在模板文件使用:

html 复制代码
<script type='text/javascript' src='/static/js/common.js'>
<link rel="stylesheet" type="text/css" href="/static/css/style.css"/>

系统提供了 load 标签来简化上面的导入:

html 复制代码
{load href="/static/js/common.js" /}
{load href="/static/css/style.css" /}

支持同时加载多个资源文件,多个资源文件之间以","号分隔,例如:

html 复制代码
{load href="/static/js/common.js,/static/css/style.css" /}

系统还提供了两个标签别名 js 和 css,用法和 load 一致,例如:

html 复制代码
{js href="/static/js/common.js" /}
{css href="/static/css/style.css" /}

5、原生 PHP

5.1、使用 php 标签

例如:

html 复制代码
{php}echo 'Hello,world!';{/php}

建议需要使用PHP代码的时候尽量采用 php 标签,因为原生的PHP语法可能会被配置禁用而导致解析错误。

5.2、使用原生PHP代码

php 复制代码
<?php echo 'Hello,world!'; ?>

注意:php 标签或者php代码里面不能再使用标签(包括普通标签和XML标签)了。

6、定义标签

6.1、assign 标签

assign 标签用于在模板文件中定义变量,用法如下:

html 复制代码
{assign name="var" value="123" /}

在运行模板的时候,赋值了一个 var 的变量,值是 123。

value 属性也支持变量,例如:

html 复制代码
{assign name="var" value="$val" /}

6.2、define 标签

define 标签用于模板中定义常量,用法如下:

html 复制代码
{define name="DEFINE_NAME" value="test" /}

在运行模板的时候,就会定义一个 DEFINE_NAME 的常量。

value 属性可以支持变量(包括系统变量),例如:

html 复制代码
{define name="DEFINE_NAME" value="$val" /}
相关推荐
JaguarJack3 小时前
如何使用 PHP 的 for、while 和 foreach 循环实现极致性能与零 Bug 代码
后端·php
BingoGo3 小时前
如何使用 PHP 的 for、while 和 foreach 循环实现极致性能与零 Bug 代码
后端·php
lskblog14 小时前
PHP中正确处理HTTP响应:从原始响应到JSON数组的完整指南
http·json·php·laravel
万岳软件开发小城17 小时前
2026 在线教育新趋势:网校系统源码正在重塑教育培训平台开发模式
人工智能·php·在线教育系统源码·教育平台搭建·教育app开发·教育软件开发
iCxhust19 小时前
linux /etc 目录 etc是什么缩写
linux·运维·服务器·php
豌豆学姐20 小时前
Sora2 能做什么?25 秒视频生成 API 的一次接入实践
大数据·人工智能·小程序·aigc·php·开源软件
wangxingps1 天前
phpmyadmin版本对应的各php版本
服务器·开发语言·php
lzjava20241 天前
LangChain4j RAG检索增强生成
php
豌豆学姐1 天前
123 口播数字人 API 接入实战:附完整前后端开源项目
大数据·php·uniapp·开源软件