视图模板
引擎驱动
MVC中,M模型-V视图-C控制器;View就是视图;
composer require topthink/think-view
namespace app\controller;
use think\facade\View;
class Show
{
// 模块引擎测试控制器
public function index()
{
return View::fetch('index');
}
}
模板使用,文件目录默认在View目录中,二级目录和当前类名一致
模板配置
默认情况下config/view.php是默认模板引擎的配置文件
不使用模板引擎,可以在控制器类中通过require()方法引入PHP文件混编
class Show
{
// 模块引擎测试控制器
public function index()
{
$name = 'mirror';
// 混编模式
// 需要配置完整的文件路径
require 'static/index.php';
}
}
如果需要给PHP文件传参并调用,可以在控制器进行;由于控制器类引入文件,PHP文件也就可以引用控制器类方法中的方法参数。
模板变量
assign() 方法
进行全局模板变量的赋值;设置向模板提供赋值操作:
// 支持字符串设置
assign('变量名','变量名');
// 支持数组设置
assign([
'变量名1'=>'变量名1',
'变量名2'=>'变量名2',
......
]);
namespace app\controller;
use think\facade\View;
class Show
{
// 模块引擎测试控制器
public function index()
{
View::assign('name','mirror');
return View::fetch('index');
}
}
在模块中只需要通过{变量名}方法来获取控制器中的值;
ThinkPHP_V6.0.2 . <?php echo $name;?>
ThinkPHP_V6.0.2 . {$name}
支持使用filter()方法对模块的变量赋值进行过滤操作
fetch()方法
fetch()方法的第二参数,可以直接用数组形式给模板传递变量;
return View::fetch('index',[
'name'=>'mirror',
'age' => 100
]);
助手函数view()
与View::fetch()同样效果
模板路径
默认情况下,自动定位模板文件路径(优先定位应用目录下view目录)。
不过也可以采用一种分离view的方法,在系统目录下创建一个view目录
单应用模式
├─app
│ └─view(视图目录)
│ ├─index index控制器目录
│ │ └─index.html index模板文件
│ └─ ... 更多控制器目录
多应用模式
├─app
│ ├─app1 (应用1)
│ │ └─view(应用视图目录)
│ │ ├─index index控制器目录
│ │ │ └─index.html index模板文件
│ │ └─ ... 更多控制器目录
│ │
│ └─ app2... (更多应用)
如果你需要自定义view目录名称,可以通过设置view_dir_name配置参数。
'view_dir_name' => 'template',
模板渲染
模板渲染的典型方法是fetch();系统会按照默认规则自动定位视图目录下的模板文件
控制器名(小写+下划线)/ 操作名.html|.php
配置auto_rule参数的值来改变当前操作的自动渲染规则。
auto_rule配置
自动定位规则
1
操作方法的小写+下划线
2
操作方法全部转换小写
3
保持和操作方法一致
除了在配置文件中修改意外,可以在控制端动态修改配置
// 修改默认的视图模板目录
View::config(['view_dir_name'=>'view'])
默认情况下,调用的是本控制器的模板文件,但也可以调用其他控制器的模板文件;
如果是多模块多应用模式,可以实现跨模块调用模板文件
View::fetch('admin@User/index');
如果想调用public公共目录的模板文件,可以用../public/***来实现:
View::fetch('../public/test/index.php');
视图模板的目录结构只是为了命名规范,无乱是怎样的目录、文件名都可以实现调用;如果不指定目录,只表明模块文件名,就会调用当前控制器模板目录下的模板文件。
第二种原生 PHP 执行方式:在 return 之前设置的变量或者模版变量均无效; 而是把所有的要传递的变量,通过 fetch()的第二个参数传递;
return View::engine('php')->fetch('index', [
'name' => 'Mr.Lee', 'age' => 100
]);
直接渲染内容 display
namespace app\index\controller;
use think\facade\View;
class Index
{
public function index()
{
// 直接渲染内容
$content = '{$name}-{$email}';
return View::display($content, ['name' => 'thinkphp', 'email' => 'thinkphp@qq.com']);
}
}
模板变量输出
当程序运行的时候会在runtime/temp目录下生成一个编译文件;默认情况下,输出的模板变量会自动进行过滤:
传递的是数组:在模板区域可以使用$data.name形式输出:
class Show
{
// 模块引擎测试控制器
public function index()
{
$arr = ['name'=>'Mirror','age'=>100];
return View::fetch('output',[
'arr' => $arr
]);
}
}
ThinkPHP_V6.0.2 . {$arr.name}
ThinkPHP_V6.0.2 . {$arr.age}
temp临时编译文件:
ThinkPHP_V6.0.2 . <?php echo htmlentities($arr['name']); ?>
ThinkPHP_V6.0.2 . <?php echo htmlentities($arr['age']); ?>
这里明显的对输出的变量进行了函数过滤
传递的是对象:$obj->name $obj::PI
class Show
{
public $name = 'Mirror';
public $age = '100';
const PI = 3.14;
// 模块引擎测试控制器
public function index()
{
return View::fetch('index',[
'obj' => $this
]);
}
}
ThinkPHP_V6.0.2 . {$obj->name}
ThinkPHP_V6.0.2 . {$obj->age}
ThinkPHP_V6.0.2 . {$obj::PI}
ThinkPHP_V6.0.2 . <?php echo htmlentities($obj->name); ?>
ThinkPHP_V6.0.2 . <?php echo htmlentities($obj->age); ?>
ThinkPHP_V6.0.2 . <?php echo htmlentities($obj::PI); ?>
变量为空时输出默认值:
{$obj->age|default=100}
echo htmlentities((isset($obj->age) && ($obj->age !== '')?$obj->age:100));
?>
系统变量:
$_SERVER $_ENV $_GET $_POST $_REQUEST $_SESSION $_COOKIE
对于注入Request对象,可以直接在模板输出
{$Request.get.id}
{$Request.host}
模块函数和运算符
使用函数
MD5加密:
{$password|md5}
不进行htmlentities转义,可以使用|raw
{$user['email']|raw}
系统内置了下面几个固定的过滤规则(不区分大小写)
过滤方法
描述
date
日期格式化(支持各种时间类型)
format
字符串格式化
upper
转换为大写
lower
转换为小写
first
输出数组的第一个元素
last
输出数组的最后一个元素
default
默认值
raw
不使用(默认)转义
多个参数调用,可以用逗号隔开;
支持多个函数进行操作,用|隔开即可,左优先;
在模板中也可以直接使用PHP的语法模式,使用:开头即可;
运算符
在模块中可以使用运算符:+ - * / % ++ --
在模块中也支持使用三元运算符;
模块的循环标签
{foreach}循环
首先在控制端中通过模型类把数据库的数据给拿出来,然后在模型端使用{foreach}闭合标签把数据实现循环;这里需要注意的是:foreach是属于对象调用,用->或.均可以实现数据调用。
public function index()
{
$list = User::select();
return View::fetch('index',[
'list' => $list
]);
}
{foreach $list as $key=>$obj}
{$key}/{$obj->id}{$obj->username}{$obj->gender}{$obj->email}{$obj->price}{$obj->create_time}{/foreach}
{volist}循环
volist也是可以将数据集通过循环方式输出:
{volist name="list" id="obj"}
{$key}/{$obj->id}{$obj->username}{$obj->gender}{$obj->email}{$obj->price}{$obj->create_time}{/volist}
volist中的name属性表示数据总集,id属性表示当前循环的单条数据集;offset属性设置数据起始位置,length属性设置数据结束位置
使用eq比较标签:
{volist name="list" id="obj" mod="2"}
{eq name='mod' value='0'}
mod=2表示索引除以2得到的余数是否等于0或1;eq标签中设置了value属性为0,也就是说需要得到的余数为0,那么可以被输出的都是偶数数据集;
使用empty标签:当没有索引数据集为空时输出
{volist name="list" id="obj" empty="Null"}
{for}循环
for循环就是通过起始和结束值的设定,按照指定的步长实现循环:
{for start='1' end='10' comparison='lt' step='2' name="list"}
{$list}
{/for}
模板的比较标签
系统支持的比较标签以及所表示的含义分别是:
标签
含义
eq或者 equal
等于
neq 或者notequal
不等于
gt
大于
egt
大于等于
lt
小于
elt
小于等于
heq
恒等于
nheq
不恒等于
{eq}
{eq}...{/eq}标签:比较两个值是否相同,相同则输出标签包含的内容;
{eq name="name" value="Mirror"}
I am Mirror.
{/eq}
属性name里是一个变量,可以选择性添加$符号;而value里是一个字符串,如果value是一个变量的化,那么就需要加上$符号使其成为一个变量。
{eq}标签支持{else/}操作:
{eq name="name" value="Mirror"}
I am Mirror.
{else/}
I not Mirror
{/eq}
所有的比较标签都可以统一为{compare}标签使用,设置type属性即可:
{compare name="name" value="Mirror" type='eq'}
......
{/compare}
模板的定义标签
变量定义{assign}
如果想在模板文件中定义一个变量,可以使用{assgin}标签
{assgin name='var' value='123'}
{$var}
常量定义{define}
{define name='PI' value='3.14'}
{$PI}
原生定义{php}
可以采用{php}标签编写原生PHP代码
{php}
echo "ThinkPHPV6.0.2";
{/php}
标签之间支持嵌套功能
模板的条件判断标签
{switch}
{switch number}
{case 1}1{/case}
{case 2}2{/case}
{case 3}3{/case}
{default/}Not
{/switch}
{if}
{if $number > 10}大于10{/if}
支持and、or等语法的使用;支持{else/}语法、{elseif}语法等多级嵌套;
{if}标签支持PHP原生语法
范围判断标签
{in}/{notin} 判断值是否存在或不存在指定数据列表中:
{in name='list' value='10,20,30,40,50,60'}存在{/in}
{in name='list' value='10,20,30,40,50,60'}
......
{else/}
......
{/in}
{between}/{notbetween}判断值是否存在或不存在数据区间
{present}/{notpresent}判断变量是否已经定义赋值
{empty}/{notempty}判断是否为空
{defined}/{notdefined}判断是否定义常量
上述各类的判断标签均支持多级嵌套,同时也支持{else/}标签的嵌套
模板的加载包含输出
包含文件{include}
{include file='模版文件1,模版文件2,...' [其它参数传递]/}
可用来加载公用重复的文件,比如头部、尾部、导航部分;
可以包含一个完整的路径;
模板的参数也可以通过固定的语法进行传递:在执行包含操作中将参数一同向被包含文件传递,在被包含文件中用[变量名]的方式来调用被一传递过来的参数:
{include file='public/header' title='$title' key='$name'}
输出替换
项目中有时需要调用静态文件,比如css和js等;写路径比较繁琐,可以路径整理打包:(在view.php中添加配置)
// 模板替换输出
'tpl_replace_string'=>[
'__JS__'=>'../static/js',
'__CSS__'=>'../static/css'
]
配置添加后,在html文件端直接调用__CSS__/__JS__(魔术方法)即可
需要重新编译程序
文件加载
传统的调用css/js文件,采用link和script标签实现调用;think系统提供了一个独特的加载方式;
使用{load}标签和href属性来链接加载,不需要设置其他任何参数:
{load href='__CSS__/layui.css'}
{load href='__JS__/jquery.js'}
{load href='__CSS__/layui.css , __JS__/jquery.js'}
// 为了方便理解 还有如下别名识别
{css href='__CSS__/layui.css'}
{js href='__JS__/jquery.js'}
模板布局
方法一:(不推荐)
6.0版本 默认情况下,不支持模板布局功能,需要在配置文件view.php中开启;
'layout_on'=> true,
发现报错提示“模板文件不存在: tp6\view\layout.html”;缺少layout.html模板;
'layout_name' => 'public/layout'
这个时候就开启了相当于全局的模板布局,我们之前的block在访问的时候就会讨厌该html文件的布局进行显示;只需要执行如下:
{__CONTENT__}
就可以把文件套用到当前布局文件中
个人表示这种方式非常的不灵活,不推荐该方法
方法二:(推荐)
无需在配置文件中设置模板布局文件了!只需要在文件的首部引入:
{layout name="[模板布局文件位置]" replace='魔术方法'}
view/block/index.html
{layout name="public/layout" replace="[__blockIndex__]"}
Block.html - {$title}
view/public/layout.html
[__blockIndex__]
这个方法比方法一更加灵活!
模板继承
模板继承是另一种灵活的HTML布局方式!
view/block/index.html
{extend name="../view/public/base.html"}
{block name="haeder"}block-test{/block}
view/public/base.html:模板布局-基模板
{$title}{block name="haeder"}base-test{/block}
{block name="nav"}base-test{/block}
在base中添加{block}标签即是一个可被替换的块域;
而index.html中继承base同时也会使用{block}标签来替换base中的块域
杂项
{literal} 原生输出
可以将{}内容原样输出,使其不被模板解析
模板注释
使用{//} {/*..*/} 等两种注释方式
表单令牌