# 活的系統
我們更愿意去打造有著良好用戶體驗的系統,雖然這樣會提升成本,但沒有比用戶滿意更重要的了。
顯然,每添加一個用戶,我們都需要修改源代碼是很不現實的。鑒于此,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';
}
~~~
測試結果如下圖所示:

## 引入V層
基本上可以這樣說,如果你用到HTML,那么就會有V層的出現。
~~~
public function add()
{
$htmls = $this->fetch();
return $htmls;
}
~~~
對應的add.html文件如下圖所示:

如果對V層文件的位置還不是很清楚的話,你需要現在回去再看一遍3.2.5小節的內容。
測試結果如下圖所示:

## 定制表單
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`表示:本函數執行到此結束。
測試結果如下:

點擊保存后,跳轉至insert 。

~~~
git checkout -f step3.3.2.1
~~~
執行上述命令后,上述示例代碼信息如下:
C層:

V層:

我們看到,數據以POST方式傳入了,并且insert也可以正確接收。
> 如果還不太清楚$_POST,你需要GOOGLE一下,最好也一并GOOGLE一下$_GET。
## 使用內置類獲取變量
在thinkphp中,為了防止sql注入(一種非常常見的攻擊手法),我們在取一些系統變量信息時,使用thinkphp提供給我們的Request來獲取用戶輸入的變量。
> 變量獲取 http://www.hmoore.net/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;
}
~~~
測試結果如下圖所示:

默認點擊上圖中的【保存】按鈕后,跳轉至如下頁面:

我們發現使用`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',
~~~
我們在用戶名處,輸入&<兩個特殊的符號,然后點擊保存進行測試:

我們看到 &< 兩個符號變成了 `&<`。
這是出于安全的角度上考慮的。至于為什么這樣就安全了,什么時候我們需要停用安全過濾,我們爭取在后續進階教程中給大家講解。
在這里,我們只需要知道在config.php文件中,設置過濾方法后,再使用Resquest::instance()->post() 來獲取post數據,就可以了,這樣做的目的是為保證數據更加安全。
~~~
git checkout -f step3.3.2.2
~~~
執行上述命令后,上述示例代碼信息如下:

在配置文件config.php中設置過濾方法如下所示:

- 序言
- 第一章 準備知識
- 第一節: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
- 第二節:查看日志
- 第十三章:總結