模型自动时间戳和自读字段

一.模型自动时间戳

系统自动创建和更新时间戳功能默认是关闭状态;
如果你想全局开启,在 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 会自动更新时间;
自动时间戳只能在模型下有效,数据库方法不可以使用;
如果创建和修改时间戳不是默认定义的,也可以自定义;

  1. protected
  2. $createTime
  3. =
  4. 'create_at';
  5. protected
  6. $updateTime
  7. =
  8. '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();
同样,只读字段只支持模型方式不支持数据库方式;

模型类型转换和数据完成

一.模型数据转换

系统可以通过模型端设置写入或读取时对字段类型进行转换;
在模型端设置你想要类型转换的字段属性,属性值为数组;

  1. protected $type
  2. =
  3. [
  4. 'price'
  5. =>
  6. 'integer',
  7. 'status'
  8. =>
  9. 'boolean',
  10. 'create_time'
  11. =>
  12. 'datetime:Y-m-d'
  13. ];

数据库查询读取的字段很多都是字符串类型,我们可以转换成如下类型:
integer(整型)、float(浮点型)、boolean(布尔型)、array(数组)
object(对象)、serialize(序列化)、json(json)、timestamp(时间戳)
datetime(日期)
由于数据库没有那么多类型演示,常用度不显著,我们提供几个方便演示的;

  1. public function typeConversion()
  2. {
  3. $user = UserModel::get(21);
  4. var_dump($user->price);
  5. var_dump($user->status);
  6. var_dump($user->create_time);
  7. }

类型转换还是会调用属性里的获取器等操作,编码时要注意这方面的问题;

二.模型数据完成

模型中数据完成通过 auto、insert 和 update 三种形式完成;
auto 表示新增和修改操作,insert 只表示新增,update 只表示修改;

  1. protected
  2. $auto
  3. =
  4. ['email'];
  5. protected
  6. $insert
  7. =
  8. ['uid'=>1];
  9. protected
  10. $update
  11. =
  12. [];

先理解 insert,当我们新增一条数据时会触发新增数据完成;
此时,并不需要自己去新增 uid,它会自动给 uid 赋值为 1;、

  1. $user = new
  2. UserModel();
  3. $user->username
  4. =
  5. '李白';
  6. $user->password
  7. =
  8. '123';
  9. $user->gender
  10. =
  11. '男';
  12. $user->email
  13. =
  14. 'libai@163.com';
  15. $user->price
  16. =
  17. 100;
  18. $user->details
  19. =
  20. '123';
  21. $user->save();

auto 表示新增和修改均要自动完成,而不给默认值的字段需要修改器提供;

  1. public function setEmailAttr($value)
  2. {
  3. return strtoupper($value);
  4. }

新增时,邮箱字符串会被修改器自动完成大写,那数据完成的意义何在?
修改时,如果你不去修改邮箱,在数据自动完成强制完成,会自动完成大写;
也就是说,邮箱的大写,设置 update 更加合适,因为新增必填必然触发修改器;
对于 update 自动完成,和 auto、insert 雷同,自行演示;

模型查询范围与输出

一.模型查询范围

在模型端创建一个封装的查询或写入方法,方便控制器端等调用;
比如,封装一个筛选所有性别为男的查询,并且只显示部分字段 5 条;
方法名规范:前缀 scope,后缀随意,调用时直接把后缀作为参数使用;

  1. public function scopeGenderMale($query)
  2. {
  3. $query->where('gender', '男')
  4. ->field('id,username,gender,email')->limit(5);
  5. }

在控制器端,我们我们直接调用并输出结果即可;

  1. public function queryScope()
  2. {
  3. $result =
  4. UserModel::scope('gendermale')->select();
  5. //$result
  6. = UserModel::gendermale()->select();
  7. return json($result);
  8. }

也可以实现多个查询封装方法连缀调用,比如找出邮箱 xiao 并大于 80 分的;

  1. public function scopeEmailLike($query, $value)
  2. {
  3. $query->where('email', 'like', '%'.$value.'%');
  4. }
  5. public function scopePriceGreater($query, $value)
  6. {
  7. $query->where('price', '>', 80);
  8. }
  9. $result = UserModel::emailLike('xiao')->priceGreater(80)
  10. ->select();

查询范围只能使用 find()和 select()两种方法;
全局范围查询,就是在此模型下不管怎么查询都会加上全局条件;

  1. //全局范围查询
  2. protected function base($query)
  3. {
  4. $query->where('status', 1);
  5. }

在定义了全局查询后,如果某些不需要全局查询可以使用 useGlobalScope 取消; UserModel::useGlobalScope(false)
当然,设置为 true,则开启全局范围查询,注意:这个方法需要跟在::后面; UserModel::useGlobalScope(true)

二.模型输出方式

通过模版进行数据输出;

  1. public function view()
  2. {
  3. $user = UserModel::get(21);
  4. $this->assign('user', $user);
  5. return $this->fetch();
  6. }

根据错误提示,可以创建相对应的模版,然后进行数据显示;
{$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 字段,直接通过数组的方式即可完成;

  1. $data = [
  2. 'username'
  3. =>
  4. '辉夜',
  5. 'password'
  6. =>
  7. '123',
  8. 'gender'
  9. =>
  10. '女',
  11. 'email'
  12. =>
  13. 'huiye@163.com',
  14. 'price'
  15. =>
  16. 90,
  17. 'details'
  18. =>
  19. '123',
  20. 'uid'
  21. =>
  22. 1011,
  23. 'status'
  24. =>
  25. 1,
  26. 'list'
  27. =>
  28. ['username'=>'辉夜', 'gender'=>'女',
  29. 'email'=>'huiye@163.com'],
  30. ];
  31. Db::name('user')->insert($data);

从上面写入可以看出,list 字段设置的就是 json,通过数组写入的就是 json;
但是,如果我要写入 details 这个 text 文本格式的字段,通过数组会报错;
这个时候,采用->json([‘details’])方法来进行转换,也可以写入 json 数据;

  1. 'details'
  2. =>
  3. ['content'=>123],
  4. Db::name('user')->json(['details'])->insert($data);

在查询上,也可以使用->json([‘list,details’])方法来获取数据;

  1. $user = Db::name('user')->json(['list','details'])
  2. ->where('id', 173)->find();
  3. return json($user);

如果要将 json 字段里的数据作为查询条件,可以通过如下方式实现:

  1. $user = Db::name('user')->json(['list','details'])->
  2. where('list->username', '辉夜')->find();

如果想完全修改 json 数据,可以使用如下的方式实现:

  1. $data['list'] = ['username'=>'李白', 'gender'=>'男'];
  2. Db::name('user')->json(['list'])
  3. ->where('id', 174)->update($data);

如果只想修改 json 数据里的某一个项目,可以使用如下的方式实现:

  1. $data['list->username'] = '李黑';
  2. Db::name('user')->json(['list'])
  3. ->where('id', 174)->update($data)

二.模型JSON

使用模型方式去新增包含 json 数据的字段;

  1. $user = new UserModel();
  2. $user->username
  3. =
  4. '李白';
  5. $user->password
  6. =
  7. '123';
  8. $user->gender
  9. =
  10. '男';
  11. $user->email
  12. =
  13. 'libai@163.com';
  14. $user->price
  15. =
  16. 100;
  17. $user->uid
  18. =
  19. 1011;
  20. $user->status
  21. =
  22. 1;
  23. $user->details
  24. =
  25. ['content'=>123];
  26. $user->list
  27. =
  28. ['username'=>'辉夜', 'gender'=>'女
  29. ','email'=>'huiye@163.com','uid'=>1011];
  30. $user->save();

对于本身不是 json 字段,想要写入 json 字段的字符字段,需要设置;

  1. protected $json = ['details', 'list'];

也可以通过对象的方式,进行对 json 字段的写入操作;

  1. $list = new \StdClass();
  2. $list->username
  3. =
  4. '辉夜';
  5. $list->gender
  6. =
  7. '女';
  8. $list->email
  9. =
  10. 'huiye@163.com';
  11. $list->uid
  12. =
  13. 1011;
  14. $user->list
  15. =
  16. $list;

通过对象调用方式,直接获取 json 里面的数据;

  1. $user = UserModel::get(179);
  2. return $user->list->username;

通过 json 的数据查询,获取一条数据;

  1. $user = UserModel::where('list->username',
  2. '辉夜')->find();
  3. return $user->list->email;

更新修改 json 数据,直接通过对象方式即可;

  1. $user = UserModel::get(179);
  2. $user->list->username =
  3. '李白';
  4. $user->save()

软删除

一.数据库的软删除

所谓软删除,并不是真的删除数据,而是给数据设置一个标记;
首先,我们需要在数据表创建一个 delete_time,默认为 NULL;
其次,使用软删除功能,软删除其实就是 update 操作,创建一个时间标记;

  1. Db::name('user')->where('id', 192)
  2. ->useSoftDelete('delete_time', date('Y-m-d H:i:s'))
  3. ->delete();
  4. 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 目录;

二.视图渲染

在控制器端,我们首先继承一下控制器基类(不是必须的,助手函数也行);
先采用第一种不带任何参数的最典型的做法(自动定位),看它报错信息;

  1. class See extends Controller
  2. {
  3. public function index()
  4. {
  5. //自动定位
  6. return $this->fetch();
  7. }
  8. }

模版路径为:当前模块/view/当前控制器名(小写)/当前操作(小写).html
如果你想制定一个输出的模版,可以在 fetch()方法传递相应的参数;

  1. return
  2. $this->fetch('edit');
  3. //指定模版
  4. return
  5. $this->fetch('public/edit');
  6. //指定目录下的模版
  7. return
  8. $this->fetch('admin@public/edit');
  9. //指定模块下的模版
  10. return
  11. $this->fetch('/edit');
  12. //view_path 下的模版

如果没有继承 Controller 控制器的话,可以使用助手函数 view()方法; return view(‘edit’);

视图赋值与过滤

一.视图赋值

在继承控制器基类的情况下,我们可以使用 assign()方法进行赋值;
$this->assign(‘name’, ‘ThinkPHP’);
//{$name}
也可以通过数组的方式,进行多个变量的赋值;

  1. $this->assign([
  2. 'username'
  3. =>
  4. '辉夜',
  5. //{$username}
  6. 'email'
  7. =>
  8. 'huiye@163.com'
  9. //{$email}
  10. ]);

assign()方法和 fetch()方法也可以合二为一进行操作;

  1. return $this->fetch('index', [
  2. 'username'
  3. =>
  4. '辉夜',
  5. 'email'
  6. =>
  7. 'huiye@163.com'
  8. ]);

使用 display()方法,可以不通过模版直接解析变量;

  1. $content = '{$username}.{$email}';
  2. return $this->display($content, [
  3. 'username'
  4. =>
  5. '辉夜',
  6. 'email'
  7. =>
  8. 'huiye@163.com'
  9. ]);

使用 view()助手函数实现渲染并赋值操作;

使用 View::share()静态方法,可以在系统任意位置做全局变量赋值;
\think\facade\View::share(‘key’, ‘value’);
//也支持数组

二.视图过滤

如果需要对模版页面输出的变量进行过滤,可以使用 filter()方法;

  1. $this->assign([
  2. 'username'
  3. =>
  4. '辉 1 夜',
  5. 'email'
  6. =>
  7. 'huiye@163.com'
  8. ]);
  9. return $this->filter(function($content){
  10. return str_replace("1",'<br/>',$content);
  11. })->fetch();

这里的$content 表示所有的模版变量,找到 1 之后,实现换行操作;
如果控制器有 N 个方法,都需要过滤,可以直接在初始化中全局过滤;

  1. public function initialize()
  2. {
  3. return $this->filter(function($content){
  4. return str_replace("1",'<br/>',$content);
  5. });
  6. }

也可以使用助手函数实现模版变量的过滤功能;

  1. return view()->filter(function($content){
  2. return str_replace("1",'<br/>',$content);
  3. })

模板变量的输出

一.变量输出

上一节课视图赋值讲到过,模版的变量的输出方式,控制器实现赋值; $this->assign(‘name’, ‘ThinkPHP’);
当模版位置创建好后,输出控制器的赋值变量时,说你用花括号和$符号; {$name}
当程序运行的时候,会在 runtime/temp 目录下生成一个编译文件; <?php echo htmlentities($name); ?>
如果传递的值是数组,那么编译文件也会自动相应的对应输出方式;

  1. $data['username']
  2. =
  3. '辉夜';
  4. $data['email']
  5. =
  6. 'huiye@163.com';
  7. $this->assign('user',
  8. $data);

模版调用:{$user.username}.{$user.email} //或{$user[‘email’]}
编译文件:<?php echo htmlentities($user[‘username’]); ?>
如果传递的值是对象,那么编译文件也会自动相应的对应输出方式;

  1. $obj = new \stdClass();
  2. $obj->username
  3. =
  4. '辉夜';
  5. $obj->email
  6. =
  7. 'huiye@163.com';
  8. $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}
系统还提供了一些固定的过滤方法,如下image.png
$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=’没有值’}
模版也可以实现三元运算,包括其它写法;

  1. {$name
  2. ? '正确'
  3. : '错误'}
  4. //$name 为 true 返回正确,否则返回错误
  5. {$name
  6. ?= '真'}
  7. //$name 为 true 返回真
  8. {$Think.get.name ?? '不存在'}
  9. //??用于系统变量,没有值时输出
  10. {$name ?: '不存在'}
  11. //?:用于普通变量,没有值时输出

三元运算符也支持运算后返回布尔值判断;
{$a == $b ? ‘真’ : ‘假’}

模板的循环标签

一.foreach循环

控制前端先通过模型把相应的数据列表给筛选出来;

  1. $list = UserModel::all();
  2. $this->assign('list', $list);
  3. return $this->fetch('user');

在模版端使用对称的标签{foreach}…{/foreach}实现循环;

  1. {foreach $list as $key=>$obj}
  2. {$key}.{$obj.id}.{$obj.username}({$obj.gender})
  3. .{$obj.email}<br>
  4. {/foreach}

其中$list 是控制前端传递的数据集,$key 是 index 索引,$obj 是数据对象;
也可以在模版中直接执行模型数据调用,而不需要在控制器设置;

  1. {foreach :model('user')->all() as $key=>$obj}
  2. {$key}.{$obj.id}.{$obj.username}({$obj.gender})
  3. .{$obj.email}<br>
  4. {/foreach}

二.volist循环

volist 也是将查询得到的数据集通过循环的方式进行输出;

  1. {volist name='list' id='obj'}
  2. {$key}.{$obj.id}.{$obj.username}({$obj.gender})
  3. .{$obj.email}<br>
  4. {/volist}

volist 中的 name 属性表示数据总集,id 属性表示当前循环的数据单条集;
volist 也可以直接使用模型对象获取数据集的方式进行循环输出;

  1. {volist name=':model("user")->all()' id='obj'}
  2. {$key}.{$obj.id}.{$obj.username}({$obj.gender})
  3. .{$obj.email}<br>
  4. {/volist}

使用 offset 属性和 length 属性从第 4 条开始显示 5 条,这里下标从 0 开始;

  1. {volist name='list' id='obj' offset='3' length='5'}
  2. {$key}.{$obj.id}.{$obj.username}({$obj.gender})
  3. .{$obj.email}<br>
  4. {/volist}

可以使用 eq 标签(下节课比较标签的知识点),来实现奇数或偶数的筛选数据;

  1. {volist
  2. name='list' id='obj' mod='2'}
  3. {eq
  4. name='mod' value='0'}
  5. {$key}.{$obj.id}.{$obj.username}({$obj.gender})
  6. .{$obj.email}<br>
  7. {/eq}
  8. {/volist}

通过编译文件可以理解,mod=2 表示索引除以 2 得到的余数是否等于 0 或 1;
如果余数设置为 0,那么输出的即偶数,如果设置为 1,则输出的是奇数;
当然,切换到其它数字,也会有更多的排列效果;
使用 empty 属性,可以当没有任何数据的时候,实现输出指定的提示;

  1. {volist name=':model("user")->where("id", 1000)->all()'
  2. id='obj' empty='没有任何数据'}
  3. {$key}.{$obj.id}.{$obj.username}({$obj.gender})
  4. .{$obj.email}<br>
  5. {/volist}

empty 属性,可以是控制器端传递过来的变量,比如:empty=’$empty’;
使用 key=’k’,让索引从 1 开始计算,不指定就用{$i},指定后失效;

  1. {volist name='list' id='obj' key='k'}
  2. {$k}.{$key}.{$obj.id}.{$obj.username}({$obj.gender})
  3. .{$obj.email}<br>
  4. {/volist}

三.for循环

for 循环,顾名思义,通过起始和终止值,结合步长实现的循环;

  1. {for start='1' end='100' comparison='<' step='2' name='i'}
  2. {$i}
  3. {/for}

模板的比较和定义标签

一.比较标签

  1. {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}

    二.定义标签

  2. 如果你想在模版文件中去定义一个变量,可以使用{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}可以实现多个条件判断;
    1. {switch number}
    2. {case
    3. 1}1{/case}
    4. {case
    5. 5}5{/case}
    6. {case
    7. 10}10{/case}
    8. {default/}不存在
    9. {/switch}
    {case}也支持多个条件判断,使用|线隔开即可;
    {case 10|20|30}10,20,30 均可{/case}
    {case}后面也可以是变量,设置变量后不可以使用|线;
    {case $id}

    二.if

  3. 使用简单条件判断的{if}标签;
    {if $number > 10}大于 10{/if}
    2. {if}标签的条件判断可以使用 AND、OR 等语法;
    {if ($number > 10) OR ($number > 5)}大于 10{/if}
    3. {if}标签支持{else/}语法;
    1. {if $number > 10}
    2. 大于 10
    3. {else/}
    4. 小于 10
    5. {/if}
  4. {if}标签也支持{elseif}多重条件判断;
    1. {if $number > 100}
    2. 大于 100
    3. {elseif $number > 50}
    4. 大于 50
    5. {else}
    6. 小于 50
    7. {/if}
  5. {if}标签中的条件判断支持 PHP 写法,比如函数和对象调用;
    1. {if strtoupper($user->name) == 'MR.LEE'}
    2. 确认李先生
    3. {/if}

    三.范围标签

  6. 范围标签:{in}和{notin},判断值是否存在或不存在指定的数据列表中;
    1. {in
    2. name='number'
    3. value='10,20,30,40,50'}存在{/in}
    4. {in
    5. name='number'
    6. value='10,20,30,40,50'}
    7. 存在数据列表中
    8. {else/}
    9. 不存在数据列表中
    10. {/in}
  7. name 值可以是是系统变量,比如$Think.xxx.yyy,value 可以是变量;
    3. 范围标签:{between}和{notbetween},判断值是否存在或不存在数据区间中;
    1. {between
    2. name='number'
    3. value='10,50'}存在{/between}
    4. {between
    5. name='number'
    6. value='10,50'}
    7. 存在数据区间中
    8. {else/}
    9. 不存在数据区间中
    10. {/between}
  8. between 中的 value 只能是两个值,表示一个区间,第三个值会无效;
    5. 区间不但可以表达数字,也可以是字母,比如 a-z,A-Z; 、

    四.是否存在标签

  9. 是否存在:{present}和{notpresent}判断变量是否已经定义赋值(是否存在);
    1. {present
    2. name='user'}存在{/present}
    3. {present
    4. name='user'}
    5. user 已存在
    6. {else/}
    7. user 不存在
    8. {/present}
  10. 是否为空:{empty}和{notempty}判断变量是否为空值;
    1. {empty
    2. name='username'}有值{/empty}
    3. {empty
    4. name='username'}
    5. username 有值
    6. {else/}
    7. username 没值
    8. {/empty}
  11. 常量是否定义:{defined}判断常量是否定义(是否存在);
    1. {defined name='PI'}
    2. PI 存在
    3. {else/}
    4. PI 不存在
    5. {/defined}

    模块加载包含输出等

    一.包含文件

    使用{include}标签来加载公用重复的文件,比如头部、尾部和导航部分;
    在模版 view 目录创建一个 public 公共目录,分别创建 header、footer 和 nav;
    然后创建 Block 控制器,引入控制器模版 index,这个模版包含三个公用文件;
    1. {include
    2. file='public/header,public/nav'/}
    3. index
    4. {include
    5. file='public/footer'/}
    也可以包含一个文件的完整路径,包括后缀,如下:
    {include file=”../application/view/public/nav.html”/}
    模版的标题和关键字,可以通过固定的语法进行传递;
    对于标题,在控制器先设置一下标题变量,然后设置{include}设置属性;
    1. $this->assign('title', '模版');
    2. {include file='public/header'
    3. title='$title' keywords='这是一个模版!'/}
    切换到 public/header.html 模版页面,使用[xxx]的方式调用数据;

    二.输出替换

    有时,我们需要调用一些静态文件,比如 css/js 等;
    一般来说,我们将这些静态文件存放在根目录 public/static/css(或 js);
    那么,直接写完整路径,比较繁长,可以把这些路径整理打包;
    在目前二级目录下,template.php 中,配置新增一个参数;
    1. 'tpl_replace_string' => [
    2. '__JS__' => 'static/js',
    3. '__CSS__' => 'static/css',
    4. ]
    如果是在顶级域名下,直接在改成/static/css 即可,加一个反斜杠;
    html 文件调用端,直接通过CSS(JS)配置的魔术方法调用即可;
    1. <link rel="stylesheet"
    2. type="text/css" href="__CSS__/basic.css">
    3. <script type="text/javascript" src="__JS__/basic.js"></script>
  12. 在测试的时候,由于是更改的配置文件刷新,每次都要删除编译文件才能生效;

    三.文件加载

    传统方式调用 CSS 或 JS 文件时,采用 link 和 script 标签实现;
    系统提供了更加智能的加载方式,方便加载 CSS 和 JS 等文件;
    使用{load}标签和 href 属性来链接,不需要设置任何其它参数;
    1. {load
    2. href='__CSS__/basic.css'/}
    3. {load
    4. href='__JS__/basic.js'/}
    也支持 href 多属性值的写法,如下:
    {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’}

    1. 首页

    2. 分类

    3. 关于


    {/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}

    二.模版注释

  13. 对于在 HTML 页面中的标签,用 HTML 注释是无效的,需要模版定义的注释;
    {//$name}
    {/$name/}
    {/
    多行注释
    /}
    2. 注释和{符号之间不能有空格,否则无法实现注释隐藏;
    3. 生成编译文件后,注释的内容会自动被删除,不会显示

    三.标签扩展

  14. 标签库分为内置和扩展标签,内置标签库是 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;