一個簡單的CRUD示例:使用PHP+MySQL
前情
老是據說CRUD
,但一直不清楚是作什麼的,就去查了一下,大概的意思是一組常見的數據庫操做:增(create)、查(read)、改(update)刪(delete),大概是,也有其餘的翻譯,這裏大概瞭解一下就好。截止到如今,網上好像沒有什麼很小的示例來闡述CRUD
這個概念的,而後就去查了一番資料,寫了一個真的很小白的、很簡單、未使用任何框架的案例。javascript
前端準備
因爲筆者對前端知識並不熟悉,這裏只貼容器(傳輸/返回數據的容器)代碼,在服務器根目錄下新建文件crud.html
,代碼以下:php
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>CRUD操做</title> </head> <body> <!-- Read:顯示數據 --> <button id="read">read</button><br> <!-- 引入JavaScript文件 --> <script src="./crud.js"></script> </body> </html>
這段代碼只有一個按鈕,設定爲點擊即顯示全部的用戶(辣雞筆者想不出什麼合適的示例,先將就着看)。 因爲不喜歡在HTML中嵌套PHP代碼,故這裏使用JavaScript來傳遞先後端的數據。在同級目錄下新建文件crud.js
,代碼以下:html
'use strict'; let read = document.getElementById('read'); if (read) { read.addEventListener('click', function () { let server = './crud.php'; let param = 'action=read'; get(server, param); }); } function get(server, param = '') { let request = new XMLHttpRequest(); request.open('GET', server); request.send(param); request.onreadystatechange = function () { if (request.readyState === 4 && request.status === 200) { let data = JSON.parse(request.responseText); console.log(data); } }; }
能夠看到,上面的JavaScript代碼中定義了一個get()
函數,該函數建立了一個使用GET
傳遞對象的XMLHttpRequest
對象,也就是常說的Ajax,這裏不作過多贅述,詳情可看:Ajax。前端
而函數get()
上方的代碼則是獲取read按鈕元素,並監聽(addEventListener
)其點擊事件,一旦用戶點擊該按鈕,則訪問同目錄下的crud.php
文件,並傳遞參數action=read
。 咱們設定判斷用戶操做的參數爲action
,而獲取數據的參數值爲read
,而後交給後端處理。vue
後端處理
前端負責傳輸數據後,後端就該負責處理數據了。java
1. 建庫建表
既然是關於數據庫的操做,那麼數據庫中必需要有數據,數據能夠參考筆者的《PHP 與 MySQL 配合的小案例:使用數據接口填充本身的數據庫》,也能夠自行添加測試數據。這裏筆者用的是user
表,剛建的測試表,只有三行數據,表數據以下:mysql
SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID', `name` varchar(30) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '暱稱', `pwd` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '加密後的密碼', `gender` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '性別', `profile` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '簡介', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = 'user' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES (1, 'ds', 'dsdsds', 1, 'dwwadsa'); INSERT INTO `user` VALUES (2, 'dsa', 'wdqdqd', 0, 'dasdfsaf'); INSERT INTO `user` VALUES (3, 'reg.lynn@qq.com', 'dsdsds', 0, ''); SET FOREIGN_KEY_CHECKS = 1;
2. 鏈接數據庫
數據庫鏈接類,可參考這篇文章中的代碼,這裏再也不書寫。sql
3. 處理數據
前面的JavaScript代碼中,咱們將CRUD
要訪問的文件設置爲同級目錄下的crud.php
(實際開發確定是要分開的,但這裏僅做示例),因而,在同級目錄下新建文件crud.php
,並輸入如下代碼:數據庫
<?php require_once './app/db/Connection.php';// 1. 引入數據庫鏈接類Connection.php文件 use db\Connection; $conn = Connection::getInstance();// 2. 鏈接數據庫 $action = 'read';// 3. 設置CRUD操做默認值:read if (isset($_GET['action'])) $action = $_GET['action'];// 4. 若是前端發來了操做代碼,則換成前端須要的操做 switch ($action) {// 5. 根據不一樣操做使用不一樣的處理方式:這裏使用 switch 結構,也可使用 if case 'create':// 6. 前端操做值爲 create 時 break; case 'read':// 7. 前端操做值爲 read 時 $sql = 'SELECT * FROM `user`'; $stmt = $conn->prepare($sql); if ($stmt->execute()) { $res['user'] = $stmt->fetchAll(PDO::FETCH_ASSOC); } else { $res['error'] = true; $res['message'] = '獲取信息失敗!'; } break; case 'update':// 8. 前端操做值爲 update 時 break; case 'delete':// 9. 前端操做值爲 dalete 時 break; } header("Content-type:application/json");// 10. 告知瀏覽器返回的數據爲JSON格式 echo json_encode($res, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);// 11. 返回JavaScript可解析的JSON數據 exit;
上面的代碼使用註釋解釋了其用途,這裏說一下case 'read':
代碼塊。咱們在這裏使用PDO
預處理獲取user表所有數據的SQL語句(PDO::prepare()
),而後執行(PDO::execute()
),最後獲取查詢的全部行(PDOStatement::fetchAll()
)並保存在一個數組中。 爲避免查詢失敗後無返回數據,在執行查詢結果時添加了錯誤處理,並給出提示信息(else
語句塊)。最後返回帶有數據或錯誤信息的JSON數據。json
這裏是筆者的查詢結果截圖:
剩餘部分
-
./user.html
文件<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>CRUD操做</title> </head> <body> <!-- Read:顯示數據 --> <button id="read">read</button><br> <!-- 在JS中使用 FormData() 方法構造表單 --> <label for="name"><input type="text" name="username" id="name" placeholder="請輸入暱稱"></label><br> <label for="pwd"><input type="password" name="userpwd" id="pwd" placeholder="請輸入密碼"></label><br> <label for="gender"><select name="usergender" id="gender"> <option value="1">男</option> <option value="0">女</option> </select></label> <br> <button id="create">create</button> <button id="update">update</button> <button id="delete">delete</button> <!-- 引入JavaScript文件 --> <script src="./crud.js"></script> </body> </html>
-
./crud.js
文件'use strict'; let read = document.getElementById('read'); if (read) { read.addEventListener('click', function () { let server = './crud.php'; let param = 'action=read'; get(server, param); }); } let create = document.getElementById('create'); if (create) { create.addEventListener('click', function () { let formdata = new FormData(); let name = document.getElementById('name').value; let pwd = document.getElementById('pwd').value; let gender = document.getElementById('gender').value; formdata.append('username', name); formdata.append('userpwd', pwd); formdata.append('usergender', gender); let server = './crud.php?action=create';// 傳遞數據時可能有POST也可能有GET數據,只能用一次方法,於是將GET參數直接添加在連接中 post(server, formdata); }); } let update = document.getElementById('update'); if(update) { update.addEventListener('click', function(){ let formdata = new FormData(); let name = document.getElementById('name').value; let pwd = document.getElementById('pwd').value; let gender = document.getElementById('gender').value; formdata.append('username', name); formdata.append('userpwd', pwd); formdata.append('usergender', gender); let server = './crud.php?action=update';// 傳遞數據時可能有POST也可能有GET數據,只能用一次方法,於是將GET參數直接添加在連接中 post(server, formdata); }); } let del = document.getElementById('delete'); if(del) { del.addEventListener('click', function(){ let formdata = new FormData(); let name = document.getElementById('name').value; let pwd = document.getElementById('pwd').value; let gender = document.getElementById('gender').value; formdata.append('username', name); formdata.append('userpwd', pwd); formdata.append('usergender', gender); let server = './crud.php?action=delete';// 傳遞數據時可能有POST也可能有GET數據,只能用一次方法,於是將GET參數直接添加在連接中 post(server, formdata); }); } function post(server, param = '') { let request = new XMLHttpRequest(); request.open('POST', server); request.send(param); request.onreadystatechange = function () { if (request.readyState === 4 && request.status === 200) { let data = JSON.parse(request.responseText); console.log(data); } }; } function get(server, param = '') { let request = new XMLHttpRequest(); request.open('GET', server); request.send(param); request.onreadystatechange = function () { if (request.readyState === 4 && request.status === 200) { let data = JSON.parse(request.responseText); console.log(data); } }; }
-
./crud.php
文件<?php /** * 根據前端請求,進行 crud 操做 * * 對 user 表進行增刪查改 */ require_once './app/db/Connection.php'; use db\Connection; $conn = Connection::getInstance(); $action = 'read'; if (isset($_GET['action'])) $action = $_GET['action']; switch ($action) { case 'create': $username = $_POST['username']; $userpwd = $_POST['userpwd']; $usergender = (int)$_POST['usergender']; $sql = 'INSERT INTO `user`(`name`,`pwd`,`gender`) VALUES (:name, :pwd, :gender)'; $stmt = $conn->prepare($sql); $stmt->bindParam(':name', $username); $stmt->bindParam(':pwd', $userpwd); $stmt->bindParam(':gender', $usergender); if ($stmt->execute()) { $res['message'] = '數據插入成功!'; } else { $res['error'] = true; $res['message'] = '數據插入失敗!'; } break; case 'read': $sql = 'SELECT * FROM `user`'; $stmt = $conn->prepare($sql); if ($stmt->execute()) { $res['user'] = $stmt->fetchAll(PDO::FETCH_ASSOC); } else { $res['error'] = true; $res['message'] = '獲取信息失敗!'; } break; case 'update': $username = $_POST['username']; $userpwd = $_POST['userpwd']; // 更新以前應該檢查該用戶是否存在,不過若是是在已肯定列表中更新,則不須要 $sql = 'UPDATE `user` SET `pwd` = :pwd WHERE `name` = :name'; $stmt = $conn->prepare($sql); $stmt->bindParam(':name', $username); $stmt->bindParam(':pwd', $userpwd); if ($stmt->execute()) { $res['message'] = '數據更新成功!'; } else { $res['error'] = true; $res['message'] = '數據更新失敗!'; } break; case 'delete': $username = $_POST['username']; $sql = 'DELETE FROM `user` WHERE `name` = :name'; $stmt = $conn->prepare($sql); $stmt->bindParam(':name', $username); if ($stmt->execute()) { $res['message'] = '數據刪除成功!'; } else { $res['error'] = true; $res['message'] = '數據刪除失敗!'; } break; } header("Content-type:application/json"); echo json_encode($res, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); exit;
代碼提要
JavaScript:Ajax
function post(server, param = '') { let request = new XMLHttpRequest(); request.open('POST', server); request.send(param); request.onreadystatechange = function () { if (request.readyState === 4 && request.status === 200) { let data = JSON.parse(request.responseText); console.log(data); } }; }
解析:
- 建立
XMLHttpRequest
對象 - 使用
POST
或GET
打開服務器server
- 發送數據
param
,例如:name=Linnzh
,name=Linnzh&age=23
。若是傳輸的參數包含特殊符號(好比雙引號"
),可以使用encodeURIComponent()
函數進行處理 - 請求成功時處理返回的數據
request.responseText
(純文本數據),返回JSON字符串時須要使用JSON.parse()
函數解析爲JSON對象
JavaScript:生成表單
let formdata = new FormData(); let name = document.getElementById('name').value; let pwd = document.getElementById('pwd').value; let gender = document.getElementById('gender').value; formdata.append('username', name); formdata.append('userpwd', pwd); formdata.append('usergender', gender);
爲啥要使用這個方法呢?由於不想在HTML文件中僅建立一個Button
就必須使用一個from
,並且不能自定義控制數據的傳輸方式。
解析:
- 建立表單數據對象:
FormData()
- 獲取表單元素(
input
等)的值 - 將表單值添加至表單數據對象:
formdata.append('username', name);
- 最後使用合適的傳輸方法進行傳輸
JavaScript:一次性發送兩種不一樣傳輸方式的數據時的解決方案
在這個例子中,增長、刪除和更新操做,都須要經過POST
發送數據(避免明文發送敏感數據),而數據庫操做則只須要經過GET
發送。若是分紅兩次發送,則會形成數據缺失,也形成重複請求。 由於GET
方式一般只用來傳輸簡短的、不重要的信息,故在數據量不小的狀況下直接添加在要訪問的URL
中,而後POST
訪問該添加了GET
參數的URL便可,以下:
let server = './crud.php?action=delete';// 傳遞數據時可能有POST也可能有GET數據,只能用一次方法,於是將GET參數直接添加在連接中 post(server, formdata);
PHP:PDO預處理
始終建議使用PDO預處理語句操做數據庫。
$username = $_POST['username']; $userpwd = $_POST['userpwd']; $usergender = (int)$_POST['usergender']; $sql = 'INSERT INTO `user`(`name`,`pwd`,`gender`) VALUES (:name, :pwd, :gender)'; $stmt = $conn->prepare($sql); $stmt->bindParam(':name', $username); $stmt->bindParam(':pwd', $userpwd); $stmt->bindParam(':gender', $usergender); if ($stmt->execute()) { $res['message'] = '數據插入成功!'; }
- 預處理SQL:
PDO::prepare($sql)
- 綁定參數:若是不須要綁定則省略該步。推薦使用命名綁定,
PDOStatement::bindParam()
- 執行預處理語句:
PDOStatement::execute()
- 從查詢結果集中獲取數據:
PDOStatement::fetchAll(PDO::FETCH_ASSOC)
簡單的CRUD示例差很少就是這樣,若是有合適的項目+好看的UI就更好了。有機會補上。