#MVC
有一种设计模式叫做MVC,我们现在已经接触了可以被用户直接触发的C,也有了可以直接访问数据表的M,还差一个叫做视图的V(View)。
我们比喻的官方一些,MVC是这样的:
从用户发送数据开始,经历1-2-3-4-5-6步,再将数据返回给用户。如下图所示:
![](https://box.kancloud.cn/2016-06-13_575e5befcb576.png)
当然了,在没有使用V以前,我们传递数据的过程是1-2-3-6。
对于MVC的理解,下图可能更加直观:
![](https://box.kancloud.cn/2016-08-01_579ef65fad719.png)
推荐学习以下视频:
http://www.imooc.com/video/5019
## 引用V层
没错,V层就是用来对数据进行包装的。
那么C层呢,C层就是个大指挥官,它从这边拿点数据,从那边拿点数据,让这个处理处理,让那个处理处理。然后让这个包装一下,让那个包装一下,最后它感觉满意了,再把包装好的产品一并返回给用户。
M层呢?就是用来被C层调用的,我们前面已经讲过了怎么调用M层,本节主要讲怎么调用V层。
### 引用think\Controller
引用后代码如下:
~~~
<?php
namespace app\index\controller; // 该文件位于application\index\controller文件夹
use think\Controller; // 用于与V层进行数据传递
use app\common\model\Teacher; // 教师模型
/**
* 教师管理,继承think\Controller后,就可以利用V层对数据进行打包了。
*/
class TeacherController extends Controller
{
public function index()
{
$Teacher = new Teacher;
$teachers = $Teacher->select();
// 向V层传数据
// 取回打包后的数据
// 将数据返回给用户
}
}
~~~
### 建立V层文件
和C层一样,V层文件的位置也是固定的,每一个V层文件默认对应一个action。
我们看到,V层的文件,位于同模块下的view文件夹下,与控制器的名字和方法的名字相对应。如下图所示:
![](https://box.kancloud.cn/0de080899f8c97d20d465ed4b767155a_713x248.png)
**注意Teahcer文件夹名与控制器名完全对应(大小写),并省略Controller后缀。**
V层文件(application\index\view\Teacher\index.html)代码如下:
~~~
Hello I am V of TeahcerController\index
~~~
V层代码位置如下图所示:
![](https://box.kancloud.cn/91b8f143d6f6d50d31543af76fc6b7b7_760x233.png)
### 补齐C层代码
~~~
public function index()
{
$Teacher = new Teacher;
$teachers = $Teacher->select();
// 向V层传数据
$this->assign('teachers', $teachers);
// 取回打包后的数据
$htmls = $this->fetch();
// 将数据返回给用户
return $htmls;
}
~~~
测试结果显示如下:
![](https://box.kancloud.cn/726795404a0a5f9847dfa55f6e80845f_412x75.png)
在上述方法中,我们使用了$this->assign()调用了其父类(think\Controller)中的assign()函数。如果我们忘记在定义类时,做继承操作,那么将会出现以下错误:
**Call to undefined method app\index\controller\TeacherController::assign()**
译为:调用了一个在app\index\controller\TeacherController中没有被定义的assign()方法。解决的方法当然也很简单了,将`class TeacherController`改为`class TeacherController extends Controller`就可以了。
> 什么是$this? 简单来说,$this = 我自己,$this->assign()调用我自己(自己没有就找父类,父类没有就找父父类)的assign()方法。前面已经讲过了,我们这个类是没有,但是它的父类有,正是我们继承了think\Controller,所以我们也就可以在TeacherController里面使用think\Controller中的方法。
### 在V层中查看变量
我们在V层中的文件index.html中,输入以下代码:
~~~
<!--在V层中使用php的函数需要类似于这样使用-->
{:var_dump($teachers)}
~~~
测试结果显示如下:
![](https://box.kancloud.cn/b32820e3b2690c87199bd6d883c0fa84_678x368.png)
没有什么技巧,这东西是thinkphp规定好的,我们记住就可以了,至于为什么可以这样用,我们在后续进阶教程中会专门针对「标签」这个东西,与大家进行详细的交流。
#### assign()
我们再来看下Think\Controller中的assign()函数:
~~~
/**
* 模板变量赋值
* @access protected
* @param mixed $name 要显示的模板变量
* @param mixed $value 变量的值
* @return void
*/
protected function assign($name, $value = '')
{
$this->view->assign($name, $value);
}
~~~
有人说,什么乱七八糟的代码,我看不懂。没关系,注释能看懂就好了。
注释说的很清楚了,本函数的作用是给模板变量赋值,然后接收两个变量,一个是要显示在模板中的变量名,另一个是要传入的变量的值。
> 良好的注释习惯是通往优秀程序员的必经之路!重要的事情好像要说三遍:注释、注释、注释!
也就是说,我们也可以这样写:
~~~
public function index()
{
$Teacher = new Teacher;
$teachers = $Teacher->select();
// 向V层传数据
$this->assign('hello', $teachers);
// 取回打包后的数据
$htmls = $this->fetch();
// 将数据返回给用户
return $htmls;
}
~~~
然后我们在V层中这样输出:
~~~
{:var_dump($hello)}
~~~
当然了,大多数情况下,我们都会这样用
~~~
// 向V层传数据
$this->assign('teachers', $teachers);
~~~
原因很简单,变量名统一,更加易于记忆。
### 引入html
html代码如下:
~~~
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>教师管理</title>
</head>
<body>
<table>
<tr>
<th>序号</th>
<th>姓名</th>
<th>性别</th>
<th>邮箱</th>
<th>用户名</th>
</tr>
<tr>
<td>1</td>
<td>张三</td>
<td>男</td>
<td>11@maol.com</td>
<td>zhangsan</td>
</tr>
</table>
</body>
</html>
~~~
测试效果:
![](https://box.kancloud.cn/c7c895005da4e70b2a18c967b10b1fd7_413x107.png)
测试发现整体没有问题后,我们继续,如果有界面不符合预期,需要先修改界面。
html的错误,直接通过firefox的查看源代码来检查,如果有错误,firefox会以红色的字体标明。
~~~
git checkout -f step3.2.5.1
~~~
执行上述命令后,上述示例代码信息如下:
C层:
![](https://box.kancloud.cn/dc1b22c4aaf68b691af75ea49b9ceb17_1112x501.png)
V层:
![](https://box.kancloud.cn/5ae73b285f43d83c5f0dc2ffb753a37e_697x519.png)
### 加入动态数据
在这里,我们用到一个标签,叫做`volist`,作用是循环输出一个数组。关于标签的知识,我们以后需要参考官方的thinkphp5快速入门教程来进行单独的学习。
> 有人说,太多了,我记不住。是的,我们也记不住。现在我们能够不查手册使用的,也就那么几个常用的标签,记住的原因还仅仅是我们用的多了而已。记住标签不是我们学习的目标,每个框架的标签都不一样,记住去哪找标签才是我们学习的目标。去哪找呢?thinkphp5官方手册!
加入volist标签后的代码如下:
~~~
<table>
<tr>
<th>序号</th>
<th>姓名</th>
<th>性别</th>
<th>邮箱</th>
<th>用户名</th>
</tr>
{volist name="teachers" id="teacher"}
<tr>
<td>1</td>
<td>张三</td>
<td>男</td>
<td>11@maol.com</td>
<td>zhangsan</td>
</tr>
{/volist}
</table>
~~~
我们再测试一遍,测试的时候,我们只是刷新一次而已,并不麻烦,不要等写了很多代码后再统一刷新测试,并不是说那种方法不可以,而是说,我们现在的水平还没有达到。测试结果如下所示:
![](https://box.kancloud.cn/2016-06-13_575e70e44a1c4.png)
我们看到成功的将张三的信息输出了两遍,说明volist成功的执行了。
现在我们再加入一行测试代码,让我们能够更清晰的看到teachers变量的结构。如下所示:
~~~
<body>
<table>
<tr>
<th>序号</th>
<th>姓名</th>
<th>性别</th>
<th>邮箱</th>
<th>用户名</th>
</tr>
{volist name="teachers" id="teacher"}
<tr>
<td>1</td>
<td>张三</td>
<td>男</td>
<td>11@maol.com</td>
<td>zhangsan</td>
</tr>
{/volist}
</table>
{:var_dump($teachers)}
</body>
~~~
测试结果如下所示:
![](https://box.kancloud.cn/1248c5790ac7afc91886501584f309ef_680x484.png)
> 永远不要认为加入测试代码是件麻烦的事情,因为你盲人摸象才是真麻烦。在使用一个数据时,必须非常清楚的知道这个数据的类型及结构。
好了,现在我们可以根据var_dump()出来的信息,进行数据的定制了。
测试信息如下:
~~~
<body>
<table>
<tr>
<th>序号</th>
<th>姓名</th>
<th>性别</th>
<th>邮箱</th>
<th>用户名</th>
</tr>
{volist name="teachers" id="teacher" key="key"}
<tr>
<td>{$key}</td>
<td>{$teacher->getData('name')}</td>
<td>{$teacher->getData('sex')}</td>
<td>{$teacher->getData('email')}</td>
<td>{$teacher->getData('username')}</td>
</tr>
{/volist}
</table>
</body>
~~~
刷新页面,测试结果如下:
![](https://box.kancloud.cn/edf07f93bf29b70a37a31b7bdbac1c0c_491x129.png)
### 解决性别为0的问题
性别为0,显然不是我们想要的。这里,我们需要用到另外一个标签 eq:即判断如果是0,则显示男,如果不是0,则显示女。
将性别一栏改写为:
~~~
<td>{eq name='teacher->getData("sex")' value='0'}男{else /}女{/eq}</td>
~~~
>{eq}{/eq}我们叫做非自闭合标签,也就是肯定有自己的另一半的。
>{else /}我们叫做自闭全标签,不需要找自己的另一半。
>是的,这和HTML一样。
测试结果如下图所示:
![](https://box.kancloud.cn/1561e6aa07ba2c89a41b3caee48c0f9f_483x129.png)
测试的时候,我们往往需要测试一个正确的,再测试一个错误的。拿到这里来讲,就是我要测试一个男,还要测试一个女。
这里的方法有两个:
1、修改数据表:这个我们还没怎么学。
2、修改代码:是的,我们用这个。
代码修改为:
~~~
<td>{eq name='teacher->getData("sex")' value='1'}男{else /}女{/eq}</td>
~~~
测试结果如下图所示:
![](https://box.kancloud.cn/2016-06-13_575e70e5171b3.png)
最后,我们恢复正常的代码,并且去除测试代码:
~~~
<body>
<table>
<tr>
<th>序号</th>
<th>姓名</th>
<th>性别</th>
<th>邮箱</th>
<th>用户名</th>
</tr>
{volist name="teachers" id="teacher" key="key"}
<tr>
<td>{$key}</td>
<td>{$teacher->getData('name')}</td>
<td>{eq name='teacher->getData("sex")' value='0'}男{else /}女{/eq}</td>
<td>{$teacher->getData('email')}</td>
<td>{$teacher->getData('username')}</td>
</tr>
{/volist}
</table>
</body>
~~~
最终,测试效果如下图所示:
![](https://box.kancloud.cn/2016-06-13_575e70e5331ed.png)
~~~
git checkout -f step3.2.5.2
~~~
执行上述命令后,上述示例代码信息如下:
![](https://box.kancloud.cn/394f9609a61de55ca5a66213e934a605_1098x568.png)
- 序言
- 第一章 准备知识
- 第一节:XAMPP
- 第二节:NAVICAT
- 第三节:GIT
- 第二章 HelloWorld
- 第一节:下载THINPHP5.0
- 第二节:启动xampp
- 第三节:hello thinkphp
- 第四节:Hello world
- 第五节:MCA
- 第六节:单引号与双引号
- 第三章 教师管理
- 第一节:新建数据库
- 第二节:CURD之R 读数据
- 3.2.1 时序图
- 3.2.2 连接数据库
- 3.2.3 直接读取数据
- 3.2.4 间接读取数据
- 3.2.5 使用V层显示数据
- 3.2.6 引入bootstrap
- 3.2.7 加入bootstrap样式
- 第三节:CURD之 C 增加数据
- 3.3.1 插入数据
- 3.3.2 表单传值
- 3.3.3 存储表单数据
- 3.3.4 自动时间戳
- 3.3.5 增加验证
- 第四节:CURD之 D 删除数据
- 3.4.1 什么是关键字
- 3.4.2 删除数据
- 3.4.3 定制删除链接
- 3.4.4 完善删除
- 第五节:CURD之 U 更新数据
- 3.5.1 读取数据
- 3.5.2 展示数据
- 3.5.3 修改数据
- 3.5.4 传递数据
- 3.5.5 接收数据
- 3.5.6 更新数据 方法一
- 3.5.7 更新数据 方法二
- 第六节:衔接各个action & 重构代码
- 3.6.1 index action
- 3.6.2 add action
- 3.6.3 insert action
- 3.6.4 delete action
- 3.6.5 edit action
- 3.6.6 update action
- 第七节:分页
- 3.7.1 调用内置分页
- 3.7.2 select与paginate(选学)
- 3.7.3 分页原理(选学)
- 3.7.4 调用page(选学)
- 第八节:模糊查询
- 3.8.1 增加查询
- 3.8.2 完善查询
- 第四章 登录与注销
- 第一节:cookie 与 session
- 第二节:静态方法
- 第三节:规划URL跳转
- 第四节:登录
- 4.4.1 登录流程
- 4.4.2 index action
- 4.4.3 login action
- 4.4.4 引入M层
- 4.4.5 异常Exception
- 第五节:注销
- 第六节:验证
- 4.6.1 action增加验证
- 4.6.2 使用构造函数验证
- 4.6.3 使用继承验证
- 第五章 E-R图与数据字典
- 第一节:第一张E-R图
- 第二节:实体间的关系
- 第三节:开发规范
- 第六章 班级管理
- 第一节:建立数据表
- 第二节:数据列表index
- 第三节:增加数据add
- 第四节:编辑数据edit
- 第五节:删除数据delete
- 第七章 学生管理
- 第一节:建立数据表
- 第二节:数据列表
- 7.2.1 显示性别
- 7.2.2 显示创建时间
- 7.2.3 显示班级名称
- 7.2.4 显示辅导员姓名
- 第三节:编辑数据
- 第四节:魔法函数
- 第五节:源码分析
- 第八章 课程管理
- 第一节:建立数据表
- 第二节:新增课程
- 第三节:编辑课程
- 8.3.1 edit
- 8.3.2 update
- 第九章 代码重构
- 第一节:add 与 edit
- 第二节:insert 与 update
- 第三节:模板继承
- 9.3.1 index.html
- 9.3.2 edit.html
- 9.3.3 小结
- 第十章 UML图
- 第一节:E-R图回顾
- 第二节:UML图
- 第十一章 菜单与路由
- 第一节:添加菜单
- 第二节:虚拟主机
- 第三节:定制路由
- 第十二章 开发调试
- 第一节:开启trace
- 第二节:查看日志
- 第十三章:总结