8.ThinkPHP视图
视图的组成
此处所说的视图就是MVC中所说的V层,视图层也要展示层。thinkphp中视图层是由HTML模板文件组成的。
也可以说视图跟模板一个意思
模板的定义
为了对模板文件更加有效的管理,ThinkPHP对模板文件进行目录划分
,默认的模板文件定义规则是:视图目录(view)/控制器名(小写)/方法名(小写)+ 模板后缀(框架的默认视图文件后缀是.html)
模板渲染
注意:在控制器中使用视图
渲染模板最常用的是控制器类在继承系统控制器基类(\think\Controller
)后调用fetch
方法,调用格式:
方式一:fetch() 的方式
return $this->fetch('[模板文件]'[,'模板变量(数组)']);
模板文件的写法支持下面几种:
用法 | 描述 |
---|---|
不带任何参数 | 自动定位当前操作的模板文件 |
[模块@]/[控制器]/[操作] | 常用写法,支持跨模块 |
完整的模板文件名 | 直接使用完整的模板文件名(包括模板后缀) |
例:
在application\index\view\index\index.html
文件中写入如下内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板渲染测试</title>
</head>
<body>
<h3>模板渲染....</h3>
</body>
</html>
在application\index\controller\Index.php
文件中写入如下内容
<?php
namespace app\index\controller;
use think\Controller;
//需要继承think\Controller
class Index extends Controller
{
public function index() {
// 不带任何参数 自动定位当前操作的模板文件
// 控制器路径: application\index\controller\Index.php
// 模板文件路径: application\index\view\index\index.html
//return $this->fetch();
//return $this->fetch('index@/index/index');
//这种默认路径就已经在application\index\view 目录下 后缀也不用写了
return $this->fetch('index/index');
}
}
运行结果
方式二:助手函数view()
推荐使用这种,不用引入,不用继承
#这里view里面的参数跟方式一写法一样
return view('[模板文件]'[,'模板变量(数组)']); # 辅助函数
# 针对于自定义路由,使用这种
return view('index@index/index');
例:
定义如下路由:
//定义控制器路由 模块/类名/方法名 路由别名
Route::get('index', 'index/index/index')->name('indexr');
注意使用模板渲染的使用访问不能使用路由别名,如上面的路由应该是/index
在application\index\controller\Index.php
文件中写入如下内容
<?php
namespace app\index\controller;
class Index
{
public function index() {
return view('index@index/index');
}
}
运行结果
模板赋值
在模板文件中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板渲染测试</title>
</head>
<body>
<h3>模板渲染....</h3>
<!-- {$变量名} 这个就是取得模板的值 -->
<h4>姓名:{$name}</h4>
<h4>年龄:{$age}</h4>
<h4>email:{$email}</h4>
</body>
</html>
方式一:$this->assign()
例:
在控制器中
<?php
namespace app\index\controller;
//需要继承\think\Controller
class Index extends \think\Controller
{
public function index() {
//单个赋值
$this->assign('name', 'makalo');
// 或者批量赋值
$this->assign([
'age' => '18',
'email' => 'makalo@qq.com'
]);
return view('index@index/index');
}
}
方式二:助手函数view()
例:
在控制器中
<?php
namespace app\index\controller;
class Index
{
public function index() {
return view('index@index/index',['name' => 'makalo','age' => '18' ,'email' => 'makalo@qq.com']);
}
}
两种方式运行结果
方式三:view()+compact () 推荐这种
模板文件如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板渲染测试</title>
</head>
<body>
<h3>模板渲染....</h3>
<h4>姓名:{$name}</h4>
<h4>年龄:{$arr['age']}</h4>
<h4>email:{$arr['email']}</h4>
</body>
</html>
控制器:
<?php
namespace app\index\controller;
class Index
{
public function index() {
$name = 'makalo';
$arr = ['age' => '18' ,'email' => 'makalo@qq.com'];
return view('index@index/index',compact('name','arr'));
}
}
运行结果
全局赋值
注意:上面的三种赋值方式只能在自己的模板内使用,那么可不可以赋值给所有模板公用?答案是可以的。
如果需要在控制器之外进行模板变量赋值,可以使用视图类的share
静态方法进行全局公共模板变量赋值,例如:
use think\facade\View;
// 赋值全局模板变量
View::share('name','value');
// 或者批量赋值
View::share(['name1'=>'value','name2'=>'value2']);
全局静态模板变量最终会和前面使用方法赋值的模板变量合并。
模板中使用函数
需要对模板输出使用函数进行过滤或其它处理的时候,就可以使用一下函数来解决。
{$password|md5}
当然也可以写成如下的写法,推荐
{:md5($password)}
注:不但可以用用php系统提供函数,还可以用tp提供的函数,还可以用户在tp规定的文件中定义的写的函数
例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{$webname}</title>
</head>
<body>
<h3>模板渲染....</h3>
<h4>姓名:{$name}</h4>
<h4>年龄:{$arr['age']}</h4>
<h4>email:{$arr['email']}</h4>
//使用函数示例
<h4>加密:{$name|md5}</h4>
<h4>加密:{:md5('aaa')}</h4>
</body>
</html>
运行结果
模板原样输出
可以使用literal
标签来防止模板标签被解析,例如:
{literal}
Hello,{$name}!
{/literal}
上面的{$name}
标签被literal
标签包含,因此并不会被模板引擎解析,而是保持原样输出。
literal
标签还可以用于页面的JS代码外层,确保JS代码中的某些用法和模板引擎不产生混淆。
总之,所有可能和内置模板引擎的解析规则冲突的地方都可以使用literal
标签处理。
例:
模板内置标签
变量输出使用普通标签就足够了,但是要完成其他的控制、循环和判断功能,就需要借助模板引擎的标签库功能了,系统内置标签库的所有标签无需引入标签库即可直接使用。
内置标签主要包括:
标签名 | 作用 | 包含属性 |
---|---|---|
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代码 | 无 |
循环标签
格式示例:
# foreach 【推荐写法】
{foreach $list as $key=>$vo }
{$vo.id}:{$vo.name}
{/foreach}
或者
# volist
{volist name="list" id="vo"}
{$vo.id}:{$vo.name}<br/>
{/volist}
例:
模板文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
<ul>
{volist name="data" id="vo"}
<li>{$vo.id} --- {$vo.name}</li>
{/volist}
{foreach $data as $val}
<li>{$val.id} --- {$val.name}</li>
{/foreach}
</ul>
</body>
</html>
控制器
<?php
namespace app\index\controller;
use think\Controller;
class Tt extends Controller
{
public function index(){
$data = [
['id' => 1, 'name' => '张三'],
['id' => 2, 'name' => '李四'],
['id' => 3, 'name' => '王五'],
['id' => 4, 'name' => '赵六'],
];
$age = 10;
return view('index@tt/index',compact('data','age'));
}
}
运行结果
条件判断标签
格式示例:
{if ( $name == 1) OR ( $name > 100) } value1
{elseif $name == 2 /} value2
{else /} value3
{/if}
例:
模板文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
<h3>条件判断</h3>
<div>
{if $age < 10} 儿童
{elseif $age<30 /} 青年
{else /} 老年
{/if}
</div>
</body>
</html>
控制器
<?php
namespace app\index\controller;
use think\Controller;
class Tt extends Controller
{
public function index(){
$data = [
['id' => 1, 'name' => '张三'],
['id' => 2, 'name' => '李四'],
['id' => 3, 'name' => '王五'],
['id' => 4, 'name' => '赵六'],
];
$age = 10;
return view('index@tt/index',compact('data','age'));
}
}
运行结果
模板继承
模板继承其实并不难理解,就好比类的继承一样,模板也可以定义一个基础模板(或者是布局),并且其中定义相关的区块(block),然后继承(extend)该基础模板的子模板中就可以对基础模板中定义的区块进行重载。
先定义一个基础模板
例:在application\index\view\common\base.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>
父模板
然后我们在子模板(其实是当前操作的入口模板)中使用继承:
application\index\view\index\ext.html 中
<!--继承父模板-->
{extend name="common/base" /}
<!--实现占位,也就是重写父模板中相应的内容-->
{block name="title"}子模板标题{/block}
{block name="left"}{/block}
{block name="main"}
子模板主内容
{/block}
{block name="right"}
子模板右边分栏
{/block}
{block name="footer"}
<!--继承父占位中的内容-->
{__block__}
--->继承父模板,并追加的内容
{/block}
子模板继承
控制器
<?php
namespace app\index\controller;
use think\Controller;
class Tt extends Controller
{
public function ext(){
return View('index@/index/ext');
}
}
运行结果