模型自动时间戳和自读字段
一.模型自动时间戳
系统自动创建和更新时间戳功能默认是关闭状态;
如果你想全局开启,在 database.php 中,设置为 true;
// 自动写入时间戳字段
‘auto_timestamp’ => true,
如果你只想设置某一个模型开启,需要设置特有字段;
//开启自动时间戳
protected $autoWriteTimestamp = true;
当然,还有一种方法,就是全局开启,单独关闭某个或某几个模型为 false;
自动时间戳开启后,会自动写入 create_time 和 update_time 两个字段;
此时,它们的默认的类型是 int,如果是时间类型,可以更改如下:
‘auto_timestamp’ => ‘datetime’,
protected $autoWriteTimestamp = ‘datetime’;
7. 都配置完毕后,当我们新增一条数据时,无须新增 create_time 会自动写入时间;
同理,当我们修改一条数据时,无须修改 update_time 会自动更新时间;
自动时间戳只能在模型下有效,数据库方法不可以使用;
如果创建和修改时间戳不是默认定义的,也可以自定义;
protected
$createTime
=
'create_at';
protected
$updateTime
=
'update_at';
如果业务中只需要 create_time 而不需要 update_time,可以关闭它;
protected $updateTime = false;
也可以动态实现不修改 update_time,具体如下:
$user->isAutoWriteTimestamp(false)->save();
二.模型只读字段
模型中可以设置只读字段,就是无法被修改的字段设置;
我们要设置 username 和 email 不允许被修改,如下:
protected $readonly = [‘username’, ‘email’];
除了在模型端设置,也可以动态设置只读字段;
$user->readonly([‘username’, ‘email’])->save();
同样,只读字段只支持模型方式不支持数据库方式;
模型类型转换和数据完成
一.模型数据转换
系统可以通过模型端设置写入或读取时对字段类型进行转换;
在模型端设置你想要类型转换的字段属性,属性值为数组;
protected $type
=
[
'price'
=>
'integer',
'status'
=>
'boolean',
'create_time'
=>
'datetime:Y-m-d'
];
数据库查询读取的字段很多都是字符串类型,我们可以转换成如下类型:
integer(整型)、float(浮点型)、boolean(布尔型)、array(数组)
object(对象)、serialize(序列化)、json(json)、timestamp(时间戳)
datetime(日期)
由于数据库没有那么多类型演示,常用度不显著,我们提供几个方便演示的;
public function typeConversion()
{
$user = UserModel::get(21);
var_dump($user->price);
var_dump($user->status);
var_dump($user->create_time);
}
类型转换还是会调用属性里的获取器等操作,编码时要注意这方面的问题;
二.模型数据完成
模型中数据完成通过 auto、insert 和 update 三种形式完成;
auto 表示新增和修改操作,insert 只表示新增,update 只表示修改;
protected
$auto
=
['email'];
protected
$insert
=
['uid'=>1];
protected
$update
=
[];
先理解 insert,当我们新增一条数据时会触发新增数据完成;
此时,并不需要自己去新增 uid,它会自动给 uid 赋值为 1;、
$user = new
UserModel();
$user->username
=
'李白';
$user->password
=
'123';
$user->gender
=
'男';
$user->email
=
'libai@163.com';
$user->price
=
100;
$user->details
=
'123';
$user->save();
auto 表示新增和修改均要自动完成,而不给默认值的字段需要修改器提供;
public function setEmailAttr($value)
{
return strtoupper($value);
}
新增时,邮箱字符串会被修改器自动完成大写,那数据完成的意义何在?
修改时,如果你不去修改邮箱,在数据自动完成强制完成,会自动完成大写;
也就是说,邮箱的大写,设置 update 更加合适,因为新增必填必然触发修改器;
对于 update 自动完成,和 auto、insert 雷同,自行演示;
模型查询范围与输出
一.模型查询范围
在模型端创建一个封装的查询或写入方法,方便控制器端等调用;
比如,封装一个筛选所有性别为男的查询,并且只显示部分字段 5 条;
方法名规范:前缀 scope,后缀随意,调用时直接把后缀作为参数使用;
public function scopeGenderMale($query)
{
$query->where('gender', '男')
->field('id,username,gender,email')->limit(5);
}
在控制器端,我们我们直接调用并输出结果即可;
public function queryScope()
{
$result =
UserModel::scope('gendermale')->select();
//$result
= UserModel::gendermale()->select();
return json($result);
}
也可以实现多个查询封装方法连缀调用,比如找出邮箱 xiao 并大于 80 分的;
public function scopeEmailLike($query, $value)
{
$query->where('email', 'like', '%'.$value.'%');
}
public function scopePriceGreater($query, $value)
{
$query->where('price', '>', 80);
}
$result = UserModel::emailLike('xiao')->priceGreater(80)
->select();
查询范围只能使用 find()和 select()两种方法;
全局范围查询,就是在此模型下不管怎么查询都会加上全局条件;
//全局范围查询
protected function base($query)
{
$query->where('status', 1);
}
在定义了全局查询后,如果某些不需要全局查询可以使用 useGlobalScope 取消; UserModel::useGlobalScope(false)
当然,设置为 true,则开启全局范围查询,注意:这个方法需要跟在::后面; UserModel::useGlobalScope(true)
二.模型输出方式
通过模版进行数据输出;
public function view()
{
$user = UserModel::get(21);
$this->assign('user', $user);
return $this->fetch();
}
根据错误提示,可以创建相对应的模版,然后进行数据显示;
{$user.username}.
{$user.gender}.
{$user.email}
使用 toArray()方法,将对象按照数组的方式输出;
$user = UserModel::get(21);
printr($user->toArray());
和之前的数据集一样,它也支持 hidden、append、visible 等方法; print_r($user->hidden([‘password,update_time’])->toArray());
toArray()方法也支持 all()和 select()等列表数据; print_r(_UserModel::select()->toArray());
使用 toJson()方法将数据对象进行序列化操作,也支持 hidden 等方法;print_r($user->toJson());
json字段
一.数据库JSON
数据库写入 JSON 字段,直接通过数组的方式即可完成;
$data = [
'username'
=>
'辉夜',
'password'
=>
'123',
'gender'
=>
'女',
'email'
=>
'huiye@163.com',
'price'
=>
90,
'details'
=>
'123',
'uid'
=>
1011,
'status'
=>
1,
'list'
=>
['username'=>'辉夜', 'gender'=>'女',
'email'=>'huiye@163.com'],
];
Db::name('user')->insert($data);
从上面写入可以看出,list 字段设置的就是 json,通过数组写入的就是 json;
但是,如果我要写入 details 这个 text 文本格式的字段,通过数组会报错;
这个时候,采用->json([‘details’])方法来进行转换,也可以写入 json 数据;
'details'
=>
['content'=>123],
Db::name('user')->json(['details'])->insert($data);
在查询上,也可以使用->json([‘list,details’])方法来获取数据;
$user = Db::name('user')->json(['list','details'])
->where('id', 173)->find();
return json($user);
如果要将 json 字段里的数据作为查询条件,可以通过如下方式实现:
$user = Db::name('user')->json(['list','details'])->
where('list->username', '辉夜')->find();
如果想完全修改 json 数据,可以使用如下的方式实现:
$data['list'] = ['username'=>'李白', 'gender'=>'男'];
Db::name('user')->json(['list'])
->where('id', 174)->update($data);
如果只想修改 json 数据里的某一个项目,可以使用如下的方式实现:
$data['list->username'] = '李黑';
Db::name('user')->json(['list'])
->where('id', 174)->update($data)
二.模型JSON
使用模型方式去新增包含 json 数据的字段;
$user = new UserModel();
$user->username
=
'李白';
$user->password
=
'123';
$user->gender
=
'男';
$user->email
=
'libai@163.com';
$user->price
=
100;
$user->uid
=
1011;
$user->status
=
1;
$user->details
=
['content'=>123];
$user->list
=
['username'=>'辉夜', 'gender'=>'女
','email'=>'huiye@163.com','uid'=>1011];
$user->save();
对于本身不是 json 字段,想要写入 json 字段的字符字段,需要设置;
protected $json = ['details', 'list'];
也可以通过对象的方式,进行对 json 字段的写入操作;
$list = new \StdClass();
$list->username
=
'辉夜';
$list->gender
=
'女';
$list->email
=
'huiye@163.com';
$list->uid
=
1011;
$user->list
=
$list;
通过对象调用方式,直接获取 json 里面的数据;
$user = UserModel::get(179);
return $user->list->username;
通过 json 的数据查询,获取一条数据;
$user = UserModel::where('list->username',
'辉夜')->find();
return $user->list->email;
更新修改 json 数据,直接通过对象方式即可;
$user = UserModel::get(179);
$user->list->username =
'李白';
$user->save()
软删除
一.数据库的软删除
所谓软删除,并不是真的删除数据,而是给数据设置一个标记;
首先,我们需要在数据表创建一个 delete_time,默认为 NULL;
其次,使用软删除功能,软删除其实就是 update 操作,创建一个时间标记;
Db::name('user')->where('id', 192)
->useSoftDelete('delete_time', date('Y-m-d H:i:s'))
->delete();
return Db::getLastSql();
此时,这条数据就被软删除了。只不过,手册并没有给出更多的操作;
二.模型软删除
介于数据库软删除没有太多的可操作的方法,官方手册推荐使用模型软操作;
首先,需要在模型端设置软删除的功能,引入 SoftDelete,它是 trait;
use SoftDelete;
protected $deleteTime = ‘deletetime’;
delete_time 默认我们设置的是 null,如果你想更改这个默认值,可以设置:
//protected $defaultSoftDelete = 0;
默认情况下,开启了软删除功能的查询,模型会自动屏蔽被软删除的数据;
$user = _UserModel::select();
return json($user);
在开启软删除功能的前提下,使用 withTrashed()方法取消屏蔽软删除的数据;
$user = UserModel::withTrashed()->select();
return json($user);
如果只想查询被软删除的数据,使用 onlyTrashed()方法即可;
$user = UserModel::onlyTrashed()->select();
return json($user);
如果想让某一条被软删除的数据恢复到正常数据,可以使用 restore()方法;
$user = UserModel::onlyTrashed()->find();
$user->restore();
8. 如果想让一条软删除的数据真正删除,在恢复正常后,使用 delete(true);
$user = UserModel::onlyTrashed()->get(193);
$user->restore();
$user->delete(true)
模板引擎和视图渲染
一.模板引擎
MVC 中,M(模型)和 C(控制器)是前面我们所了解的内容;
而 V(视图),也就是模版页面,是 MVC 中第三个核心内容;
模版引擎分为两种,一种内置的,一种外置作为插件引入的,我们用内置的即可;
内置的模版引擎的配置文件是 config/template.php;
默认情况下已经很好了,不需要修改任何参数,view_path 默认是 view 目录;
二.视图渲染
在控制器端,我们首先继承一下控制器基类(不是必须的,助手函数也行);
先采用第一种不带任何参数的最典型的做法(自动定位),看它报错信息;
class See extends Controller
{
public function index()
{
//自动定位
return $this->fetch();
}
}
模版路径为:当前模块/view/当前控制器名(小写)/当前操作(小写).html
如果你想制定一个输出的模版,可以在 fetch()方法传递相应的参数;
return
$this->fetch('edit');
//指定模版
return
$this->fetch('public/edit');
//指定目录下的模版
return
$this->fetch('admin@public/edit');
//指定模块下的模版
return
$this->fetch('/edit');
//view_path 下的模版
如果没有继承 Controller 控制器的话,可以使用助手函数 view()方法; return view(‘edit’);
视图赋值与过滤
一.视图赋值
在继承控制器基类的情况下,我们可以使用 assign()方法进行赋值;
$this->assign(‘name’, ‘ThinkPHP’);
//{$name}
也可以通过数组的方式,进行多个变量的赋值;
$this->assign([
'username'
=>
'辉夜',
//{$username}
'email'
=>
'huiye@163.com'
//{$email}
]);
assign()方法和 fetch()方法也可以合二为一进行操作;
return $this->fetch('index', [
'username'
=>
'辉夜',
'email'
=>
'huiye@163.com'
]);
使用 display()方法,可以不通过模版直接解析变量;
$content = '{$username}.{$email}';
return $this->display($content, [
'username'
=>
'辉夜',
'email'
=>
'huiye@163.com'
]);
使用 view()助手函数实现渲染并赋值操作;
使用 View::share()静态方法,可以在系统任意位置做全局变量赋值;
\think\facade\View::share(‘key’, ‘value’);
//也支持数组
二.视图过滤
如果需要对模版页面输出的变量进行过滤,可以使用 filter()方法;
$this->assign([
'username'
=>
'辉 1 夜',
'email'
=>
'huiye@163.com'
]);
return $this->filter(function($content){
return str_replace("1",'<br/>',$content);
})->fetch();
这里的$content 表示所有的模版变量,找到 1 之后,实现换行操作;
如果控制器有 N 个方法,都需要过滤,可以直接在初始化中全局过滤;
public function initialize()
{
return $this->filter(function($content){
return str_replace("1",'<br/>',$content);
});
}
也可以使用助手函数实现模版变量的过滤功能;
return view()->filter(function($content){
return str_replace("1",'<br/>',$content);
})
模板变量的输出
一.变量输出
上一节课视图赋值讲到过,模版的变量的输出方式,控制器实现赋值; $this->assign(‘name’, ‘ThinkPHP’);
当模版位置创建好后,输出控制器的赋值变量时,说你用花括号和$符号; {$name}
当程序运行的时候,会在 runtime/temp 目录下生成一个编译文件; <?php echo htmlentities($name); ?>
如果传递的值是数组,那么编译文件也会自动相应的对应输出方式;
$data['username']
=
'辉夜';
$data['email']
=
'huiye@163.com';
$this->assign('user',
$data);
模版调用:{$user.username}.{$user.email} //或{$user[‘email’]}
编译文件:<?php echo htmlentities($user[‘username’]); ?>
如果传递的值是对象,那么编译文件也会自动相应的对应输出方式;
$obj = new \stdClass();
$obj->username
=
'辉夜';
$obj->email
=
'huiye@163.com';
$this->assign('obj', $obj);
模版调用:{$obj->username}.{$obj->email}
编译文件:<?php echo htmlentities($obj->username); ?>
如果是模型对象的数据列表,数组和对象方式均可;
二.其他输出
如果输出的变量没有值,可以直接设置默认值代替;
{$user.username|default=’没有用户名’}
使用$Think.xxx.yyy 方式,可以输出系统的变量;
系统变量有:$_SERVER、$_ENV、$_GET、$_POST、$_REQUEST、$_SESSION 和$_COOKIE;{$Think.get.name}
//其它雷同
除了变量,常量也可以在模版直接输出;
{$Think.const.PHP_VERSION}
{$Think.PHP_VERSION}
系统配置也可以直接在模版输出,配置参数可以在 config 文件下;
{$Think.config.default_return_type}
模板中函数与运算符
一.使用函数
控制器端先赋值一个密码的变量,模版区设置 md5 加密操作;
$this->assign(‘password’, ‘123456’);
{$password|md5}
系统默认在编译的会采用 htmlentities 过滤函数防止 XSS 跨站脚本攻击;
如果你想更换一个过滤函数,比如 htmlspecialchars,可以在配置文件设置;
具体在 config 下的 template.php 中,增加一条如下配置即可; ‘default_filter’ => ‘htmlspecialchars’
如果在某个字符,你不需要进行 HTML 实体转义的话,可以单独使用 raw 处理; {$user[‘email’]|raw}
系统还提供了一些固定的过滤方法,如下
$this->assign(‘time’, time());
{$time|date=’Y-m-d’}
$this->assign(‘number’, ‘14’);
{$number|format=’%x’}
如果函数中,需要多个参数调用,直接用逗号隔开即可; {$name|substr=0,3}
在模版中也支持多个函数进行操作,用|号隔开即可,函数从左到右依次执行; {$password|md5|upper|substr=0,3}
你也可以在模版中直接使用 PHP 的语法模式,该方法不会使用过滤转义: {:substr(strtoupper(md5($password)), 0, 3)}
二.运算符
在模版中的运算符有+、-、*、/、%、++、—等; {$number + $number}
如果模版中有运算符,则函数方法则不再支持; {$number + $number|default=’没有值’}
模版也可以实现三元运算,包括其它写法;
{$name
? '正确'
: '错误'}
//$name 为 true 返回正确,否则返回错误
{$name
?= '真'}
//$name 为 true 返回真
{$Think.get.name ?? '不存在'}
//??用于系统变量,没有值时输出
{$name ?: '不存在'}
//?:用于普通变量,没有值时输出
三元运算符也支持运算后返回布尔值判断;
{$a == $b ? ‘真’ : ‘假’}
模板的循环标签
一.foreach循环
控制前端先通过模型把相应的数据列表给筛选出来;
$list = UserModel::all();
$this->assign('list', $list);
return $this->fetch('user');
在模版端使用对称的标签{foreach}…{/foreach}实现循环;
{foreach $list as $key=>$obj}
{$key}.{$obj.id}.{$obj.username}({$obj.gender})
.{$obj.email}<br>
{/foreach}
其中$list 是控制前端传递的数据集,$key 是 index 索引,$obj 是数据对象;
也可以在模版中直接执行模型数据调用,而不需要在控制器设置;
{foreach :model('user')->all() as $key=>$obj}
{$key}.{$obj.id}.{$obj.username}({$obj.gender})
.{$obj.email}<br>
{/foreach}
二.volist循环
volist 也是将查询得到的数据集通过循环的方式进行输出;
{volist name='list' id='obj'}
{$key}.{$obj.id}.{$obj.username}({$obj.gender})
.{$obj.email}<br>
{/volist}
volist 中的 name 属性表示数据总集,id 属性表示当前循环的数据单条集;
volist 也可以直接使用模型对象获取数据集的方式进行循环输出;
{volist name=':model("user")->all()' id='obj'}
{$key}.{$obj.id}.{$obj.username}({$obj.gender})
.{$obj.email}<br>
{/volist}
使用 offset 属性和 length 属性从第 4 条开始显示 5 条,这里下标从 0 开始;
{volist name='list' id='obj' offset='3' length='5'}
{$key}.{$obj.id}.{$obj.username}({$obj.gender})
.{$obj.email}<br>
{/volist}
可以使用 eq 标签(下节课比较标签的知识点),来实现奇数或偶数的筛选数据;
{volist
name='list' id='obj' mod='2'}
{eq
name='mod' value='0'}
{$key}.{$obj.id}.{$obj.username}({$obj.gender})
.{$obj.email}<br>
{/eq}
{/volist}
通过编译文件可以理解,mod=2 表示索引除以 2 得到的余数是否等于 0 或 1;
如果余数设置为 0,那么输出的即偶数,如果设置为 1,则输出的是奇数;
当然,切换到其它数字,也会有更多的排列效果;
使用 empty 属性,可以当没有任何数据的时候,实现输出指定的提示;
{volist name=':model("user")->where("id", 1000)->all()'
id='obj' empty='没有任何数据'}
{$key}.{$obj.id}.{$obj.username}({$obj.gender})
.{$obj.email}<br>
{/volist}
empty 属性,可以是控制器端传递过来的变量,比如:empty=’$empty’;
使用 key=’k’,让索引从 1 开始计算,不指定就用{$i},指定后失效;
{volist name='list' id='obj' key='k'}
{$k}.{$key}.{$obj.id}.{$obj.username}({$obj.gender})
.{$obj.email}<br>
{/volist}
三.for循环
for 循环,顾名思义,通过起始和终止值,结合步长实现的循环;
{for start='1' end='100' comparison='<' step='2' name='i'}
{$i}
{/for}
模板的比较和定义标签
一.比较标签
- {eq}..{/eq}标签,比较两个值是否相同,相同即输出包含内容;
$this->assign(‘username’, ‘Mr.Lee’);
{eq name=’username’ value=’Mr.Lee’}
李先生
{/eq}
2. 属性 name 里是一个变量,$符号可加可不加;而 value 里是一个字符串;
3. 如果 value 也需要是一个变量的话,那么 value 需要加上$后的变量;
{eq name=’username’ value=’$username’}
4. {eq}标签有一个别名标签:{equal},效果是一样的;
5. 相对应的{neq}或{notequal},实现相反的效果;
{neq name=’username’ value=’Mr.Wang’}
两个值不相等
{/neq}
6. 这一组标签也支持 else 操作,标签为:{else/};
{eq name=’username’ value=’Mr.Lee’}
两个值相等
{else/}
两个值不等
{/eq}
7. {gt}(>)、{egt}(>=)、{lt}(<)、{elt}(<=)、{heq}(===)和{nheq}(!==);
8. 除了相等和不等,还有上面六种比较形式;
{egt name=’number’ value=’10’}
大于等于 10
{else/}
小于 10
{/egt}
9. 所有的标签都可以统一为{compare}标签使用,增加一个 type 方法指定即可;
{compare name=’username’ value=’Mr.Lee’ type=’eq’}两个值相等
{/compare}二.定义标签
- 如果你想在模版文件中去定义一个变量,可以使用{assgin}标签;
{assign name=’var’ value=’123’}
//也支持变量 value=’$name’
{$var}
2. 有变量的定义就会有常量的定义,可以使用{define}标签;
{define name=’PI’ value=’3.1415’}
{$Think.const.PI}
3. 有时,实在不知道在模版中怎么进行编码时,可以采用{php}标签进行原生编码;
{php}
echo ‘原生编码防止脱发’;
{/php}
4. 要注意的是:原生编码就是 PHP 编码,不能再使用模版引擎的特殊编码方式;
5. 比如{eq},{$user.name}这些标签语法均不支持;
6. 标签之间,是支持嵌套功能的,比如从列表中找到“樱桃小丸子”;
{foreach $list as $key=>$obj}
{eq name=’obj.username’ value=’樱桃小丸子’}
{$key}.{$obj.id}.{$obj.username}({$obj.gender})
.{$obj.email}
{/eq}
{/foreach}模板条件判断标签
一.switch
使用{switch}…{/switch}可以实现多个条件判断;
{case}也支持多个条件判断,使用|线隔开即可;{switch number}
{case
1}1{/case}
{case
5}5{/case}
{case
10}10{/case}
{default/}不存在
{/switch}
{case 10|20|30}10,20,30 均可{/case}
{case}后面也可以是变量,设置变量后不可以使用|线;
{case $id}二.if
- 使用简单条件判断的{if}标签;
{if $number > 10}大于 10{/if}
2. {if}标签的条件判断可以使用 AND、OR 等语法;
{if ($number > 10) OR ($number > 5)}大于 10{/if}
3. {if}标签支持{else/}语法;{if $number > 10}
大于 10
{else/}
小于 10
{/if}
- {if}标签也支持{elseif}多重条件判断;
{if $number > 100}
大于 100
{elseif $number > 50}
大于 50
{else}
小于 50
{/if}
- {if}标签中的条件判断支持 PHP 写法,比如函数和对象调用;
{if strtoupper($user->name) == 'MR.LEE'}
确认李先生
{/if}
三.范围标签
- 范围标签:{in}和{notin},判断值是否存在或不存在指定的数据列表中;
{in
name='number'
value='10,20,30,40,50'}存在{/in}
{in
name='number'
value='10,20,30,40,50'}
存在数据列表中
{else/}
不存在数据列表中
{/in}
- name 值可以是是系统变量,比如$Think.xxx.yyy,value 可以是变量;
3. 范围标签:{between}和{notbetween},判断值是否存在或不存在数据区间中;{between
name='number'
value='10,50'}存在{/between}
{between
name='number'
value='10,50'}
存在数据区间中
{else/}
不存在数据区间中
{/between}
- between 中的 value 只能是两个值,表示一个区间,第三个值会无效;
5. 区间不但可以表达数字,也可以是字母,比如 a-z,A-Z; 、四.是否存在标签
- 是否存在:{present}和{notpresent}判断变量是否已经定义赋值(是否存在);
{present
name='user'}存在{/present}
{present
name='user'}
user 已存在
{else/}
user 不存在
{/present}
- 是否为空:{empty}和{notempty}判断变量是否为空值;
{empty
name='username'}有值{/empty}
{empty
name='username'}
username 有值
{else/}
username 没值
{/empty}
- 常量是否定义:{defined}判断常量是否定义(是否存在);
{defined name='PI'}
PI 存在
{else/}
PI 不存在
{/defined}
模块加载包含输出等
一.包含文件
使用{include}标签来加载公用重复的文件,比如头部、尾部和导航部分;
在模版 view 目录创建一个 public 公共目录,分别创建 header、footer 和 nav;
然后创建 Block 控制器,引入控制器模版 index,这个模版包含三个公用文件;
也可以包含一个文件的完整路径,包括后缀,如下:{include
file='public/header,public/nav'/}
index
{include
file='public/footer'/}
{include file=”../application/view/public/nav.html”/}
模版的标题和关键字,可以通过固定的语法进行传递;
对于标题,在控制器先设置一下标题变量,然后设置{include}设置属性;
切换到 public/header.html 模版页面,使用[xxx]的方式调用数据;$this->assign('title', '模版');
{include file='public/header'
title='$title' keywords='这是一个模版!'/}
二.输出替换
有时,我们需要调用一些静态文件,比如 css/js 等;
一般来说,我们将这些静态文件存放在根目录 public/static/css(或 js);
那么,直接写完整路径,比较繁长,可以把这些路径整理打包;
在目前二级目录下,template.php 中,配置新增一个参数;
如果是在顶级域名下,直接在改成/static/css 即可,加一个反斜杠;'tpl_replace_string' => [
'__JS__' => 'static/js',
'__CSS__' => 'static/css',
]
html 文件调用端,直接通过CSS(JS)配置的魔术方法调用即可;<link rel="stylesheet"
type="text/css" href="__CSS__/basic.css">
<script type="text/javascript" src="__JS__/basic.js"></script>
- 在测试的时候,由于是更改的配置文件刷新,每次都要删除编译文件才能生效;
三.文件加载
传统方式调用 CSS 或 JS 文件时,采用 link 和 script 标签实现;
系统提供了更加智能的加载方式,方便加载 CSS 和 JS 等文件;
使用{load}标签和 href 属性来链接,不需要设置任何其它参数;
也支持 href 多属性值的写法,如下:{load
href='__CSS__/basic.css'/}
{load
href='__JS__/basic.js'/}
{load
href=’CSS/basic.css, JS/basic.js’}
{load}还提供了两个别名{js}、{css}来更好的实现可读性;
{js href=’JS/basic.js’}
{css href=’CSS/basic.css’}
{js}和{css}只是别名而已,识别.js 还是.css 是根据后缀的;模板的布局与继承
一.模板布局
默认情况下,不支持模版布局功能,需要在配置文件中开启;
在配置文件 template.php 中,配置开始模版布局功能;
‘layouton’
=> true,
此时,执行上一节课的模版控制器,会发现提示缺少模版 layout.html;
这个默认的布局文件,是可以更改的,位置和名字均可配置;
‘layoutname’
=> ‘public/layout’,
我们清空上一节课 index.html 的模版代码,只写一个“主体”二字;
然后将所有的代码拷贝到 layout.html 的布局模版中去,删除本身的“主体”;
然后执行 index.html 模版时,怎么将主体嵌入到 layout.html 中去?
使用{CONTENT}类似魔术方法的标签来引入 index.html“主体”内容;
{include file=’public/header,public/nav’ title=’$title’
keywords=’这是一个模版!’/}
{include file=”../application/view/public/nav.html”/}
{CONTENT}
{include file=’public/footer’/}
你可以更改{CONTENT},只要在配置文件中配置;
‘layoutitem’
=> ‘{_REPLACE}’
再强调:再测试的时候,如果更改了配置文件,务必删除 temp 下编译文件再刷新;
上面说的是第一种,配置文件下来开启布局,而第二种方式则不需要开启直接使用;
首先,你必须关闭第一种配置,我这里就直接注释掉了,然后使用{layout}标签;
只要在 index.html 的最上面加上如下代码,即可实现模版布局;
{layout name=”public/layout” repalce=’[__CONTENT]’}
第三种,直接在控制器端执行 layout(true)方法即可,false 表示临时关闭;
$this->view->engine->layout(true);
这种方法,虽然不需要配置文件开启,但如果不用默认的路径,还是要配置路径等;二.模板继承
模版继承是另一种布局方式,这种布局的思路更加的灵活;
首先,我们要创建一个 public/base.html 的基模版文件,文件名随意;
<!DOCTYPE html>
创建一个新的方法 extend 载入新的模版 extend.html,然后加载基模版;
{extend
name=’public/base’}
{extend
name=’../application/view/public/base.html’}
对于模版基类里的变量{$title},直接在控制器设置传值即可;
$this->assign(‘title’, ‘模版’);
在基模版 base.html 中,设置几个可替换的区块部分,{block}标签实现;
{block
name=’nav’}nav{/block}
{block
name=’include’}{include file=’public:nav’}{/block}
{block
name=’footer’} @ThinkPHP 版权所有 {/block}
在 extend.html 模版中,改变 nav,变成自己所需要的部分;
{block name=’nav’}- 首页
- 分类
- 关于
{/block}
在 base.html 中,{include}可以加载内容,而在 extend.html 可以改变加载;
{block name=’include’}{include file=’public:header’}{/block}
在 base.html 中已设置的内容,可以通过{block}加载到 extend.html 中;
{block name=’footer’}
本站来自: {block} | 翻版必究
{/block}模板的一些杂项
一.原样输出
有时,我们需要输出类似模版标签或语法的数据,这时会被模版解析;
此时,我们就使用模版的原样输出标签{literal};
{literal}
变量标签形式:{$name}
{/literal}二.模版注释
- 对于在 HTML 页面中的标签,用 HTML 注释是无效的,需要模版定义的注释;
{//$name}
{/$name/}
{/
多行注释
/}
2. 注释和{符号之间不能有空格,否则无法实现注释隐藏;
3. 生成编译文件后,注释的内容会自动被删除,不会显示三.标签扩展
- 标签库分为内置和扩展标签,内置标签库是 Cx 标签库,就是我们一直用的;
2. 标签库源文件在:根目录下 thinkphp/library/think/template/taglib;
3. 其中 TagLib.php 是标签解析基类,Cx.php 是标签库解析类,继承自 TagLib;
4. 通读源代码,我们发现,基本都是我们之前所学习的标签,用法也很简单;
{eq name=’xxx’}yyy{/eq}
5. 因为 Cx 是内置标签,使用的时候是非常简洁的形式,如果是扩展标签则如下格式:
{cx:eq name=’xxx’}yyy{/cx:eq}
6. 如果自己定义一个扩展的标签库,可以按照 Cx.php,在它旁边创建 Html.php;
class Html extends TagLib
{
//定义标签列表
protected
$tags
= [
//标签定义:
attr 属性列表
close 是否闭合(0 或者 1,默认 1)
‘font’
=>
[‘attr’
=> ‘color,size’, ‘close’=>1]
];
//闭合标签
public function
tagFont($tag, $content)
{
$parseStr =
‘‘ .
$content . ‘‘;
return
$parseStr;
}
}
7. 对于,扩展标签,我们需要在模版中引入这个标签,并使用扩展标签;
{taglib name=”html”}
{html:font color=’red’ size=’10’}
我是 ThinkPHP
{/html:font}
8. 如果想把这个扩展标签库移到应用目录区,比如:application\taglib;
9. 我们这个时候,需要在 template.php 配置一下预加载标签;
// 预先加载的标签库
‘taglib_pre_load’
=>
‘app\taglib\Html’,
10. 最后,需要更改一下 Html.php 的命名空间; namespace app\taglib;