# 活的系统
我们更愿意去打造有着良好用户体验的系统,虽然这样会提升成本,但没有比用户满意更重要的了。
显然,每添加一个用户,我们都需要修改源代码是很不现实的。鉴于此,FORM这个东西就出现了,它能够获取到用户的输入,并且能够将用户的输入提交到我们指定的URL中。对于我们来讲,相当于用户把一些数据直接提交到了我们的ACTION中,那么当然我们就可以在ACTION中,对用户传入的值进行灵活的操作了。
我们一直说增删改查,但在上一节中,我们却更多的用了insert, 而不是add。这显然与SQL语句有关,因为在SQL语句中使用insert into xxx 来实现增加数,第二点呢,其实这还和FORM表单有关。
我们认为,用户只有先添加数据到FORM表单中,然后才可能实现将数据添加到数据表中的目的。
所以,我们把用户在表单中添加数据的动作,叫做add,而把数据增加到数据表中的动作,叫做insert。
即数据增加的过程实际上是:用户访问`add` -> `用户输入数据` -> `用户将数据传给insert` -> `系统将用户数据存入系统`。
## add action
~~~
public function add()
{
return 'hello add';
}
~~~
测试结果如下图所示:
![](https://box.kancloud.cn/2016-06-14_575f894a80b7d.png)
## 引入V层
基本上可以这样说,如果你用到HTML,那么就会有V层的出现。
~~~
public function add()
{
$htmls = $this->fetch();
return $htmls;
}
~~~
对应的add.html文件如下图所示:
![](https://box.kancloud.cn/bc9b2ea42b4cb94a96217bc82b9724f2_468x188.png)
如果对V层文件的位置还不是很清楚的话,你需要现在回去再看一遍3.2.5小节的内容。
测试结果如下图所示:
![](https://box.kancloud.cn/2016-06-14_575f894ab4457.png)
## 定制表单
add.html文件的代码如下:
~~~
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>新增数据</title>
</head>
<body class="container">
<div class="row">
<div class="col-md-12">
<form action="insert" method="post">
<label>姓名:</label>
<input type="text" name="name" />
<label>用户名:</label>
<input type="text" name="username" />
<label>性别:</label>
<select name="sex">
<option value="0">男</option>
<option value="1">女</option>
</select>
<label>邮箱:</label>
<input type="email" name="email" />
<button type="submit">保存</button>
</form>
</div>
</div>
</body>
</html>
~~~
此时,form表单的action指向了insert,即用户将数据传给了insert action。
下面我们将改写insert的内容,以查看数据是否以正确的方式传入并且insert已经正确接收了。
~~~
public function insert()
{
var_dump($_POST);
return ; // 提前返回
// 实例化Teacher空对象
$Teacher = new Teacher();
$Teacher->name = '王五';
$Teacher->username = 'wangwu';
$Teacher->sex = '1';
$Teacher->email = 'wangwu@yunzhi.club';
// 执行对象的插入数据操作
$Teacher->save();
// 反馈结果
return '新增成功。新增ID为:' . $Teacher->id;
}
~~~
`return`表示:本函数执行到此结束。
测试结果如下:
![](https://box.kancloud.cn/3c24f49675bb450b60b6ae49e5cdc390_732x79.png)
点击保存后,跳转至insert 。
![](https://box.kancloud.cn/1f665e51d0e85f983c2ad5b1d28e7ad2_593x174.png)
~~~
git checkout -f step3.3.2.1
~~~
执行上述命令后,上述示例代码信息如下:
C层:
![](https://box.kancloud.cn/e36fd6cd3187bc05ee1528bc9051ea08_1056x609.png)
V层:
![](https://box.kancloud.cn/f8e7a5d70a00be697ec1d2c27fa14ef6_826x610.png)
我们看到,数据以POST方式传入了,并且insert也可以正确接收。
> 如果还不太清楚$_POST,你需要GOOGLE一下,最好也一并GOOGLE一下$_GET。
## 使用内置类获取变量
在thinkphp中,为了防止sql注入(一种非常常见的攻击手法),我们在取一些系统变量信息时,使用thinkphp提供给我们的Request来获取用户输入的变量。
> 变量获取 http://www.kancloud.cn/manual/thinkphp5/118044
我们简单来看一下,使用内置Request类并正确设置后,与直接输出的区别。
将insert代码改写为:
~~~
...
use think\Request; // 引用Request
...
public function insert()
{
var_dump($_POST);
// Request::instance()返回了一个对象,调用这个对象的post()方法,得到post数据
$postData = Request::instance()->post();
var_dump($postData);
return ; // 提前返回
// 实例化Teacher空对象
$Teacher = new Teacher();
$Teacher->name = '王五';
$Teacher->username = 'wangwu';
$Teacher->sex = '1';
$Teacher->email = 'wangwu@yunzhi.club';
// 执行对象的插入数据操作
$Teacher->save();
// 反馈结果
return '新增成功。新增ID为:' . $Teacher->id;
}
~~~
测试结果如下图所示:
![](https://box.kancloud.cn/b3bbd6de366f0b3b5ceabb863af48a20_736x89.png)
默认点击上图中的【保存】按钮后,跳转至如下页面:
![](https://box.kancloud.cn/3905e07ec2292e5d10c15a1d85314b6b_581x273.png)
我们发现使用`Request::instance()->post();`同样获取到了post过来的数据。我们在分析这行语句前首先回顾下前面的内容。
* * * * *
在前面的3.2.3中,我们使用`Db::name('teacher')->select();`来获取了数据表中的数据。对比我们在这里使用的`Request::instance()->post();`不难发现`::`这个符号。在这里,我们可以把`Db::name('teacher')`理解为调用`Db`类中的`name`方法;把`Request::instance()->post();`理解为调用`Request`类中的`instance()`方法。
前面我们在提到面向对象的思想时,讲过面向对象的步骤是:先实例化一个对象,然后调用这个对象上的方法。
那么为什么这里,我们没有实例化`Db`类,却直接使用了`::`调用`name()`方法呢?
这是由于在类中有一种方法叫做**静态方法**,**静态方法**可以不进行实例化而直接使用`::`来调用。而上面的`name()`和`instance()`都是`ThinkPHP`为我们准备好的静态方法。后面的章节中,我们还会专门的对静态方法进行讲解。
* * * * *
通过测试不难看出,使用上述两种方法获取到的post数据是一致的,那么怎么防止sql注入呢?下面,我们在config.php中设置一下过滤方法:
~~~
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => 'htmlspecialchars',
~~~
我们在用户名处,输入&<两个特殊的符号,然后点击保存进行测试:
![](https://box.kancloud.cn/2016-06-14_575fa8bdc6a3a.png)
我们看到 &< 两个符号变成了 `&<`。
这是出于安全的角度上考虑的。至于为什么这样就安全了,什么时候我们需要停用安全过滤,我们争取在后续进阶教程中给大家讲解。
在这里,我们只需要知道在config.php文件中,设置过滤方法后,再使用Resquest::instance()->post() 来获取post数据,就可以了,这样做的目的是为保证数据更加安全。
~~~
git checkout -f step3.3.2.2
~~~
执行上述命令后,上述示例代码信息如下:
![](https://box.kancloud.cn/f07a561e8f80549778b653d65e9ad350_1103x571.png)
在配置文件config.php中设置过滤方法如下所示:
![](https://box.kancloud.cn/955f0594f032514f6cb39a9cdc63d480_826x386.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
- 第二节:查看日志
- 第十三章:总结