8.ThinkPHP视图

视图的组成

此处所说的视图就是MVC中所说的V层,视图层也要展示层。thinkphp中视图层是由HTML模板文件组成的。

也可以说视图跟模板一个意思

模板的定义

为了对模板文件更加有效的管理,ThinkPHP对模板文件进行目录划分,默认的模板文件定义规则是:视图目录(view)/控制器名(小写)/方法名(小写)+ 模板后缀(框架的默认视图文件后缀是.html)

image-20200524163106784

模板渲染

注意:在控制器中使用视图

渲染模板最常用的是控制器类在继承系统控制器基类(\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');

    }
}

运行结果

image-20200524172557062

方式二:助手函数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');
    }
}

运行结果

image-20200524173910382

模板赋值

在模板文件中

<!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']);
    }
}

两种方式运行结果

image-20200524175941365

方式三: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'));
    }
}

运行结果

image-20200524180856395

全局赋值

注意:上面的三种赋值方式只能在自己的模板内使用,那么可不可以赋值给所有模板公用?答案是可以的。

如果需要在控制器之外进行模板变量赋值,可以使用视图类的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>

运行结果

image-20200524185909911

模板原样输出

可以使用literal标签来防止模板标签被解析,例如:

{literal}
    Hello,{$name}!
{/literal}

上面的{$name}标签被literal标签包含,因此并不会被模板引擎解析,而是保持原样输出。

literal标签还可以用于页面的JS代码外层,确保JS代码中的某些用法和模板引擎不产生混淆。

总之,所有可能和内置模板引擎的解析规则冲突的地方都可以使用literal标签处理。

例:

image-20200524190159655

模板内置标签

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

内置标签主要包括:

标签名 作用 包含属性
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'));
    }
}

运行结果

image-20200524201230949

条件判断标签

格式示例:

{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'));
    }
}

运行结果

image-20200524201748618

模板继承

模板继承其实并不难理解,就好比类的继承一样,模板也可以定义一个基础模板(或者是布局),并且其中定义相关的区块(block),然后继承(extend)该基础模板的子模板中就可以对基础模板中定义的区块进行重载。

image-20200524203407729

先定义一个基础模板

例:在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>

父模板

image-20200524204757761

然后我们在子模板(其实是当前操作的入口模板)中使用继承:

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}

子模板继承

image-20200524205125208

控制器

<?php

namespace app\index\controller;

use think\Controller;

class Tt extends Controller
{
    public function ext(){
        return View('index@/index/ext');
    }
}

运行结果

image-20200524205504993

posted @ 2020-05-24 20:57  makalo  阅读(835)  评论(0编辑  收藏  举报