一、设计数据表
sql语句如下:
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for `yunzhi_student`
-- ----------------------------
DROP TABLE IF EXISTS `yunzhi_student`;
CREATE TABLE `yunzhi_student` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(40) NOT NULL DEFAULT '' COMMENT '姓名',
`num` varchar(40) NOT NULL DEFAULT '',
`sex` tinyint(2) NOT NULL DEFAULT '0',
`klass_id` int(11) NOT NULL DEFAULT '0',
`email` varchar(40) NOT NULL DEFAULT '',
`create_time` int(11) NOT NULL DEFAULT '0',
`update_time` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `yunzhi_student`
-- ----------------------------
BEGIN;
INSERT INTO `yunzhi_student` VALUES ('1', '徐琳杰', '111', '0', '1', 'xulinjie@yunzhiclub.com', '0', '0'), ('2', '魏静云', '112', '1', '2', 'weijingyun@yunzhiclub.com', '0', '0'), ('3', '刘茜', '113', '0', '2', 'liuxi@yunzhiclub.com', '0', '0'), ('4', '李甜', '114', '1', '1', 'litian@yunzhiclub.com', '0', '0'), ('5', '李翠彬', '115', '1', '3', 'licuibin@yunzhiclub.com', '0', '0'), ('6', '孔瑞平', '115', '0', '4', 'kongruiping@yunzhiclub.com', '0', '0');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
2.M
<?php
namespace app\common\model;
use think\Model; // 使用前进行声明
/**
* Student 学生表
*/
class Student extends Model
{
}
3.C
<?php
namespace app\index\controller;
use app\common\model\Student;
class StudentController extends IndexController
{
public function index(){
$Student=new Student;
$students=$Student->paginate();
$this->assign('students',$students);
return $this->fetch();
}
}
4.V
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>学生管理</title>
<!-- <link rel="stylesheet" type="text/css" href="/thinkphp5/public/static/bootstrap-3.3.5-dist/css/bootstrap.min.css"> -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="container">
<div class="row">
<div class="col-md-12">
<hr />
<div class="row">
<div class="col-md-8">
<form class="form-inline">
<div class="form-group">
<label class="sr-only" for="name">姓名</label>
<input name="name" type="text" class="form-control" placeholder="姓名..." value={:input('get.name')}>
</div>
<button type="submit" class="btn btn-default"><i class="glyphicon glyphicon-search"></i> 查询</button>
</form>
</div>
<div class="col-md-4 text-right">
<a href="{:url('add')}" class="btn btn-primary"><i class="glyphicon glyphicon-plus"></i> 增加</a>
</div>
</div>
<hr />
<table class="table table-hover table-bordered">
<tr class="info">
<th>序号</th>
<th>姓名</th>
<th>学号</th>
<th>性别</th>
<th>email</th>
<td>创建时间</td>
<th>班级</th>
<th>辅导员</th>
<th>操作</th>
</tr>
{volist name="students" id="student" key="key"}
<tr>
<td>{$key}</td>
<td>{$student->getData('name')}</td>
<td>{$student->getData('num')}</td>
<td>{eq name="$student->getData('sex')" value="0"}男{else /}女{/eq}</td>
<td>{$student->getData('email')}</td>
<td>{$student->getData('create_time')}</td>
<td>{$student->getData('klass_id')}</td>
<td></td>
<td><a class="btn btn-danger btn-sm" href="{:url('delete?id=' . $student->getData('id'))}"><i class="glyphicon glyphicon-trash"></i> 删除</a> <a class="btn btn-sm btn-primary" href="{:url('edit?id=' . $student->getData('id'))}"><i class="glyphicon glyphicon-pencil"></i> 编辑</a></td>
</tr>
{/volist}
</table>
{$students->render()}
</div>
</div>
</body>
</html>
二、解决几个V层显示问题
1、性别显示的问题
方法1:之前在前端用以下语法实现:
<td>{eq name="$student->getData('sex')" value="0"}男{else /}女{/eq}</td>
方法2:『获取器』实现
http://www.kancloud.cn/manual/thinkphp5/135192
1)M层
获取器必须以get+字段名+Attr()
格式命名,否则无法实现
<?php
namespace app\common\model;
use think\Model;
class Student extends Model
{
/**
*获取器:获取对应学习性别
*@param 0/1
*@return 性别
*/
public function getSexAttr($value){
$status=['0'=>'男','1'=>'女',];
$sex=$status[$value];
if(isset($sex)){//如果设置了就根据设置值返回性别
return $sex;
}else{//如果没设置默认返回男性
return $status[0];
}
}
}
2)V层
<!-- <td>{eq name="$student->getData('sex')" value="0"}男{else /}女{/eq}</td> -->
<td>{$student->sex}</td>
效果:http://tt/index.php/index/student
让我们尝试一下删除掉getSexAttr(),然后再刷新页面,发现就性别显示的变成了 0/1 而不再是男女了。
没错,你猜的对:
1、如果没有getSexAttr()函数,那么$student->getData('sex')
与$student->sex
的作用是相同的,都是返回sex的原始数据。
2、如果有了getSexAttr()函数,那么$student->getData('sex')
仍然是返回sex
的原始数据。
3、如果有了getSexAttr()函数,那么$student->sex
返回的是sex字段经过getSexAttr()
函数处理后的数据。
2、创建时间显示的问题
1.方法1
1.1)M层
/**
*获取器:根据时间戳显示时间
*@param 时间戳
*@return 时间
*/
public function getCreateTimeAttr($value){
return date('Y-m-d',$value);
}
1.2)V层
<!-- <td>{$student->getData('create_time')}</td> -->
<td>{$student->create_time}</td>
3)方法2:时间转换thinkphp封装的更好的方法
3.1 M层
由于时间戳的使用频率太频繁了,以至于thinkphp为我们封装了一个更好的方法。
http://www.kancloud.cn/manual/thinkphp5/138669
按照官方的教程,在这里,我们使用类型转换的功能,即重写$type
及$dataFormat
。
在此,我们需要先删除刚刚创建的getCreateTimeAttr方法,然后在M层中增加以下代码:
删除getCreateTimeAttr()
获取器,或重命名
/**
* 自定义自转换字换:重写$type
* @var array
*/
protected $type=[
'create_time'=>'datetime',
];
//自定义时间格式:重写$dateFormat
protected $dateFormat = 'Y年m月d日'; // 日期格式 1970年1月1日 默认格式:1970-01-01 08:00:00
3.2.V层不变
<!-- <td>{$student->getData('create_time')}</td> -->
<td>{$student->create_time}</td>
效果:http://tt/index.php/index/student
在实际项目中,我们还会对其他字段进行相应的类型转换处理,以防止有非法数据尝试写入数据库而带来系统错误。我们还会对日期的显示形式进行统一处理,这样当用户对日期的显示格式不满意时,能够通过设置某一个变量值,而达到统一更改的目的。
最后,我们再将删除掉的getCreateTimeAttr()还原回来,然后我们再刷新网页,发现日期又变回了yyyy-mm-dd的形式了。
总结:获取器及类型转换,都会对原始的数据进行二次的加工处理,其优先级顺序为:获取器(getAttrXXX) > 类型转换($type)。
3、利用关联查询显示班级名称
我们在第六章班级管理中,其实已经对这种情况进行了完美的处理。
我们简单回顾一下处理的流程:
1、增加一个同名方法;
2、在这个方法中,通过klass_id字段来获取Klass这个对象;
3、返回Klass对象。
上述流程,是我们处理n:1关系中基本不变的法则。由于这个用的实在是太频繁了,所以thinkphp5同时也内置了该功能。现在,我们尝试使用thinkphp的方法来实现查看班级名称的功能。
http://www.kancloud.cn/manual/thinkphp5/142358
关联详解:https://www.cnblogs.com/kangshuai/p/12051718.html
我们看到,原来还可以通过调用一个叫做$this->belongsTo(‘klass’);的方法来直接实现我们的需求。
我们仍然在Student 数据表模型中增加代码:
M层:
/**
* ThinkPHP使用一个叫做__get()的魔法函数来完成这个函数的自动调用
* 在本章第五节中,我们将专门对__get()进行讲解
* @author 梦云智 http://www.mengyunzhi.com
*/
public function Klass()
{
return $this->belongsTo('Klass');
}
V层修改:
//<td>{$student->Klass->name}</td> //此处原写法有误改成:
<td>{$student->Klass['name']}</td>
原因:输出{:var_dump($student->Klass)}显示:
{"id":1,"name":"实验1班","teacher_id":1,"create_time":0,"update_time":0}
因此显示name需用以上方式
测试结果为:实验一班、二班……
其实我们不需要纠结thinkphp是怎么做到的,会用就可以了。简单的事情重复做,你就是专家。现在我们需要做的,仅仅是简单的事情重复做,是的,只要你做到了,thinkphp5入门这块的专家,就是你。
如果你想在V层中,直接查看Klass这个对象,可以使用{:var_dump($Klass)};
位置如下:{$student->Klass->name}{:var_dump($student->Klass)};
总结:
我们在这里使用
s
t
u
d
e
n
t
−
>
K
l
a
s
s
获
取
到
了
K
l
a
s
s
这
个
对
象
,
它
执
行
的
流
程
基
本
上
是
这
样
的
:
有
K
l
a
s
s
这
个
字
段
吗
?
没
有
。
有
K
l
a
s
s
这
个
方
法
吗
?
有
。
执
行
K
l
a
s
s
这
个
方
法
。
返
回
了
一
个
K
l
a
s
s
对
象
。
其
实
我
们
完
全
可
以
在
K
l
a
s
s
这
个
方
法
中
,
返
回
一
个
非
K
l
a
s
s
对
象
;
也
可
以
在
一
个
非
K
l
a
s
s
方
法
中
,
返
回
K
l
a
s
s
对
象
。
只
是
在
这
里
,
我
们
更
愿
意
在
K
l
a
s
s
方
法
中
返
回
K
l
a
s
s
对
象
,
这
就
是
规
范
。
就
像
我
们
往
往
习
惯
于
使
用
student->Klass获取到了Klass这个对象,它执行的流程基本上是这样的: 有Klass这个字段吗?没有。 有Klass这个方法吗?有。 执行Klass这个方法。 返回了一个Klass对象。 其实我们完全可以在Klass这个方法中,返回一个非Klass对象;也可以在一个非Klass方法中,返回Klass对象。只是在这里,我们更愿意在Klass方法中返回Klass对象,这就是规范。就像我们往往习惯于使用
student−>Klass获取到了Klass这个对象,它执行的流程基本上是这样的:有Klass这个字段吗?没有。有Klass这个方法吗?有。执行Klass这个方法。返回了一个Klass对象。其实我们完全可以在Klass这个方法中,返回一个非Klass对象;也可以在一个非Klass方法中,返回Klass对象。只是在这里,我们更愿意在Klass方法中返回Klass对象,这就是规范。就像我们往往习惯于使用Student = new Student;而不是使用$sdfsdf = new Student;一样。规范使得团队的代码风格统一,能够使我们的代码更具有易读性。
4、利用M的关联查询显示辅导员姓名
模型的关联详解:https://www.cnblogs.com/kangshuai/p/12051718.html
1) M层:在app\commom\model\Klass.php加【注意:此处不是Student】
/**
*代替getTeacher获取对应教师对象
*/
public function Teacher(){
return $this->belongsTo('Teacher');
}
2)V层:student的v 层显示对应老师名
<!-- <pre>{:var_dump($student->Klass['Teacher'])}</pre> -->
<td>{$student->Klass['Teacher']['name']}</td>
效果:http://tt/index.php/index/student
【此处原写法】:$student->Klass->Teacher->name
无效。
【原因】:{:var_dump($student->Klass)}
输出如下
可以看到它实际上变成了多层数组,因此读取方式也发生改变
object(app\common\model\Klass)#27 (27) {
["Teacher":"app\common\model\Klass":private]=>
NULL
["connection":protected]=>
array(0) {
}
["name":protected]=>
string(5) "Klass"
["table":protected]=>
NULL
["class":protected]=>
string(22) "app\common\model\Klass"
["error":protected]=>
NULL
["validate":protected]=>
NULL
["pk":protected]=>
NULL
["field":protected]=>
array(0) {
}
["readonly":protected]=>
array(0) {
}
["visible":protected]=>
array(0) {
}
["hidden":protected]=>
array(0) {
}
["append":protected]=>
array(0) {
}
["data":protected]=>
array(6) {
["id"]=>
int(1)
["name"]=>
string(10) "实验1班"
["teacher_id"]=>
int(1)
["create_time"]=>
int(0)
["update_time"]=>
int(0)
["Teacher"]=>
object(app\common\model\Teacher)#30 (26) {
["connection":protected]=>
array(0) {
}
["name":protected]=>
string(7) "Teacher"
["table":protected]=>
NULL
["class":protected]=>
string(24) "app\common\model\Teacher"
["error":protected]=>
NULL
["validate":protected]=>
NULL
["pk":protected]=>
NULL
["field":protected]=>
array(0) {
}
["readonly":protected]=>
array(0) {
}
["visible":protected]=>
array(0) {
}
["hidden":protected]=>
array(0) {
}
["append":protected]=>
array(0) {
}
["data":protected]=>
array(8) {
["id"]=>
int(1)
["name"]=>
string(6) "张三"
["sex"]=>
int(0)
["username"]=>
string(7) "zhansan"
["password"]=>
string(40) "4758eee18cc9a2d44db45d728bd7056d9e41b06b"
["email"]=>
string(17) "zhangsan@mail.com"
["create_time"]=>
int(123123)
["update_time"]=>
int(1597024251)
}
["change":protected]=>
array(0) {
}
["auto":protected]=>
array(0) {
}
["insert":protected]=>
array(0) {
}
["update":protected]=>
array(0) {
}
["autoWriteTimestamp":protected]=>
bool(true)
["createTime":protected]=>
string(11) "create_time"
["updateTime":protected]=>
string(11) "update_time"
["dateFormat":protected]=>
string(11) "Y-m-d H:i:s"
["type":protected]=>
array(0) {
}
["isUpdate":protected]=>
bool(true)
["updateWhere":protected]=>
array(1) {
["id"]=>
array(2) {
[0]=>
string(2) "eq"
[1]=>
int(1)
}
}
["relation":protected]=>
NULL
["failException":protected]=>
bool(false)
}
}
["change":protected]=>
array(0) {
}
["auto":protected]=>
array(0) {
}
["insert":protected]=>
array(0) {
}
["update":protected]=>
array(0) {
}
["autoWriteTimestamp":protected]=>
bool(true)
["createTime":protected]=>
string(11) "create_time"
["updateTime":protected]=>
string(11) "update_time"
["dateFormat":protected]=>
string(11) "Y-m-d H:i:s"
["type":protected]=>
array(0) {
}
["isUpdate":protected]=>
bool(true)
["updateWhere":protected]=>
array(1) {
["id"]=>
array(2) {
[0]=>
string(2) "eq"
[1]=>
int(1)
}
}
["relation":protected]=>
object(think\model\Relation)#29 (11) {
["parent":protected]=>
*RECURSION*
["model":protected]=>
string(24) "app\common\model\Teacher"
["middle":protected]=>
NULL
["type":protected]=>
int(3)
["foreignKey":protected]=>
string(10) "teacher_id"
["throughKey":protected]=>
NULL
["localKey":protected]=>
string(2) "id"
["alias":protected]=>
array(0) {
}
["joinType":protected]=>
string(5) "INNER"
["query":protected]=>
object(think\db\Query)#31 (11) {
["connection":protected]=>
object(think\db\connector\Mysql)#9 (15) {
["PDOStatement":protected]=>
object(PDOStatement)#12 (1) {
["queryString"]=>
string(64) "SELECT * FROM `yunzhi_teacher` WHERE `id` = :where_id LIMIT 1 "
}
["queryStr":protected]=>
string(57) "SELECT * FROM `yunzhi_teacher` WHERE `id` = 1 LIMIT 1 "
["numRows":protected]=>
int(1)
["transTimes":protected]=>
int(0)
["error":protected]=>
string(0) ""
["links":protected]=>
array(1) {
[0]=>
object(PDO)#11 (0) {
}
}
["linkID":protected]=>
object(PDO)#11 (0) {
}
["linkRead":protected]=>
NULL
["linkWrite":protected]=>
NULL
["resultSetType":protected]=>
string(5) "array"
["fetchType":protected]=>
int(2)
["attrCase":protected]=>
int(0)
["query":protected]=>
array(3) {
["app\common\model\Student"]=>
object(think\db\Query)#10 (11) {
["connection":protected]=>
*RECURSION*
["builder":protected]=>
string(5) "mysql"
["model":protected]=>
string(24) "app\common\model\Student"
["table":protected]=>
string(0) ""
["name":protected]=>
string(7) "Student"
["pk":protected]=>
NULL
["fieldType":protected]=>
array(0) {
}
["allowField":protected]=>
array(0) {
}
["prefix":protected]=>
string(7) "yunzhi_"
["options":protected]=>
array(0) {
}
["bind":protected]=>
array(0) {
}
}
["app\common\model\Klass"]=>
object(think\db\Query)#28 (11) {
["connection":protected]=>
*RECURSION*
["builder":protected]=>
string(5) "mysql"
["model":protected]=>
string(22) "app\common\model\Klass"
["table":protected]=>
string(0) ""
["name":protected]=>
string(5) "Klass"
["pk":protected]=>
NULL
["fieldType":protected]=>
array(0) {
}
["allowField":protected]=>
array(0) {
}
["prefix":protected]=>
string(7) "yunzhi_"
["options":protected]=>
array(0) {
}
["bind":protected]=>
array(0) {
}
}
["app\common\model\Teacher"]=>
*RECURSION*
}
["config":protected]=>
array(20) {
["type"]=>
string(5) "mysql"
["hostname"]=>
string(9) "127.0.0.1"
["database"]=>
string(3) "tp5"
["username"]=>
string(4) "root"
["password"]=>
string(4) "root"
["hostport"]=>
string(0) ""
["dsn"]=>
string(0) ""
["params"]=>
array(0) {
}
["charset"]=>
string(4) "utf8"
["prefix"]=>
string(7) "yunzhi_"
["debug"]=>
bool(true)
["deploy"]=>
int(0)
["rw_separate"]=>
bool(false)
["master_num"]=>
int(1)
["slave_no"]=>
string(0) ""
["fields_strict"]=>
bool(true)
["resultset_type"]=>
string(5) "array"
["auto_timestamp"]=>
bool(true)
["sql_explain"]=>
bool(false)
["builder"]=>
string(0) ""
}
["params":protected]=>
array(5) {
[8]=>
int(0)
[3]=>
int(2)
[11]=>
int(0)
[17]=>
bool(false)
[20]=>
bool(false)
}
}
["builder":protected]=>
string(5) "mysql"
["model":protected]=>
string(24) "app\common\model\Teacher"
["table":protected]=>
string(0) ""
["name":protected]=>
string(7) "Teacher"
["pk":protected]=>
NULL
["fieldType":protected]=>
array(0) {
}
["allowField":protected]=>
array(0) {
}
["prefix":protected]=>
string(7) "yunzhi_"
["options":protected]=>
array(0) {
}
["bind":protected]=>
array(0) {
}
}
["where":protected]=>
NULL
}
["failException":protected]=>
bool(false)
}
{:var_dump($student->Klass['Teacher'])}输出查看如下:
object(app\common\model\Teacher)#30 (26) {
["connection":protected]=>
array(0) {
}
["name":protected]=>
string(7) "Teacher"
["table":protected]=>
NULL
["class":protected]=>
string(24) "app\common\model\Teacher"
["error":protected]=>
NULL
["validate":protected]=>
NULL
["pk":protected]=>
NULL
["field":protected]=>
array(0) {
}
["readonly":protected]=>
array(0) {
}
["visible":protected]=>
array(0) {
}
["hidden":protected]=>
array(0) {
}
["append":protected]=>
array(0) {
}
["data":protected]=>
array(8) {
["id"]=>
int(1)
["name"]=>
string(6) "张三"
["sex"]=>
int(0)
["username"]=>
string(7) "zhansan"
["password"]=>
string(40) "4758eee18cc9a2d44db45d728bd7056d9e41b06b"
["email"]=>
string(17) "zhangsan@mail.com"
["create_time"]=>
int(123123)
["update_time"]=>
int(1597024251)
}
["change":protected]=>
array(0) {
}
["auto":protected]=>
array(0) {
}
["insert":protected]=>
array(0) {
}
["update":protected]=>
array(0) {
}
["autoWriteTimestamp":protected]=>
bool(true)
["createTime":protected]=>
string(11) "create_time"
["updateTime":protected]=>
string(11) "update_time"
["dateFormat":protected]=>
string(11) "Y-m-d H:i:s"
["type":protected]=>
array(0) {
}
["isUpdate":protected]=>
bool(true)
["updateWhere":protected]=>
array(1) {
["id"]=>
array(2) {
[0]=>
string(2) "eq"
[1]=>
int(1)
}
}
["relation":protected]=>
NULL
["failException":protected]=>
bool(false)
}