視圖模板
引擎驅動
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');
}
}
在模塊中只需要通過
{變量名}
方法來獲取控制器中的值;
<body>
<h1>
ThinkPHP_V6.0.2 . <?php echo $name;?>
ThinkPHP_V6.0.2 . {$name}
</h1>
</body>
支持使用
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
目錄下生成一個編譯文件;默認情況下,輸出的模板變量會自動進行過濾:
<?php echo htmlentities($name)?>
傳遞的是數組:在模板區域可以使用$data.name
形式輸出:
class Show
{
// 模塊引擎測試控制器
public function index()
{
$arr = ['name'=>'Mirror','age'=>100];
return View::fetch('output',[
'arr' => $arr
]);
}
}
<body>
<h1>
ThinkPHP_V6.0.2 . {$arr.name}
<hr>
ThinkPHP_V6.0.2 . {$arr.age}
</h1>
</body>
temp臨時編譯文件:
<body> <h1> ThinkPHP_V6.0.2 . <?php echo htmlentities($arr['name']); ?> <hr> ThinkPHP_V6.0.2 . <?php echo htmlentities($arr['age']); ?> </h1> </body>
這里明顯的對輸出的變量進行了函數過濾
傳遞的是對象:$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
]);
}
}
<body>
<h1>
ThinkPHP_V6.0.2 . {$obj->name}
<hr>
ThinkPHP_V6.0.2 . {$obj->age}
<hr>
ThinkPHP_V6.0.2 . {$obj::PI}
</h1>
</body>
<body> <h1> ThinkPHP_V6.0.2 . <?php echo htmlentities($obj->name); ?> <hr> ThinkPHP_V6.0.2 . <?php echo htmlentities($obj->age); ?> <hr> ThinkPHP_V6.0.2 . <?php echo htmlentities($obj::PI); ?> </h1> </body>
變量為空時輸出默認值:
{$obj->age|default=100}
<?php
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
]);
}
<table>
{foreach $list as $key=>$obj}
<tr>
<td>{$key}/{$obj->id}</td>
<td>{$obj->username}</td>
<td>{$obj->gender}</td>
<td>{$obj->email}</td>
<td>{$obj->price}</td>
<td>{$obj->create_time}</td>
</tr>
{/foreach}
</table>
{volist}
循環
volist
也是可以將數據集通過循環方式輸出:
<table>
{volist name="list" id="obj"}
<tr>
<td>{$key}/{$obj->id}</td>
<td>{$obj->username}</td>
<td>{$obj->gender}</td>
<td>{$obj->email}</td>
<td>{$obj->price}</td>
<td>{$obj->create_time}</td>
</tr>
{/volist}
</table>
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__
(魔術方法)即可
<link rel="stylesheet" type='text/css' href="__CSS__/layui.css">
需要重新編譯程序
文件加載
傳統的調用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__]"}
<h1>
Block.html - {$title}
</h1>
view/public/layout.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
[__blockIndex__]
</body>
</html>
這個方法比方法一更加靈活!
模板繼承
模板繼承是另一種靈活的HTML布局方式!
view/block/index.html
{extend name="../view/public/base.html"}
{block name="haeder"}block-test{/block}
view/public/base.html
:模板布局-基模板
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{$title}</title>
</head>
<body>
{block name="haeder"}base-test{/block}
{block name="nav"}base-test{/block}
</body>
</html>
在base中添加{block}標簽即是一個可被替換的塊域;
而index.html中繼承base同時也會使用{block}標簽來替換base中的塊域
雜項
{literal}
原生輸出
可以將{}
內容原樣輸出,使其不被模板解析
模板注釋
使用{//}
{/*..*/}
等兩種注釋方式
表單令牌
參考官方文檔:thinkphp6-表單令牌