一个简单的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就更好了。有机会补上。