一个简单的CRUD示例:使用PHP+MySQL

一个简单的CRUD示例:使用PHP+MySQL

前情

总是听说CRUD,但一直不清楚是做什么的,就去查了一下,大概的意思是一组常见的数据库操作:增(create)、查(read)、改(update)删(delete),大概是,也有其他的翻译,这里大概了解一下就好。截止到现在,网上好像没有什么很小的示例来阐述CRUD这个概念的,然后就去查了一番资料,写了一个真的很小白的、很简单、未使用任何框架的案例。

前端准备

由于笔者对前端知识并不熟悉,这里只贴容器(传输/返回数据的容器)代码,在服务器根目录下新建文件crud.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>

    <!-- 引入JavaScript文件 -->
    <script src="./crud.js"></script>
</body>
</html>

这段代码只有一个按钮,设定为点击即显示所有的用户(辣鸡笔者想不出什么合适的示例,先将就着看)。
由于不喜欢在HTML中嵌套PHP代码,故这里使用JavaScript来传递前后端的数据。在同级目录下新建文件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);
    });
}
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,然后交给后端处理。

后端处理

前端负责传输数据后,后端就该负责处理数据了。

1. 建库建表

既然是关于数据库的操作,那么数据库中必须要有数据,数据可以参考笔者的《PHP 与 MySQL 配合的小案例:使用数据接口填充自己的数据库》,也可以自行添加测试数据。这里笔者用的是user表,刚建的测试表,只有三行数据,表数据如下:

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, '[email protected]', 'dsdsds', 0, '');

SET FOREIGN_KEY_CHECKS = 1;

2. 连接数据库

数据库连接类,可参考这篇文章中的代码,这里不再书写。

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数据。

这里是笔者的查询结果截图:

剩余部分

  • ./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对象
  • 使用POSTGET打开服务器server
  • 发送数据param,例如:name=Linnzhname=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就更好了。有机会补上。

资源与参考

  1. Ajax-Web开发者指南
  2. PHP-PDO
  3. Vue.js/PHP/MySQL增删改查CRUD示例代码_恒馨博客

原文地址:https://www.cnblogs.com/linnzh/p/11583766.html

时间: 2024-08-24 13:44:40

一个简单的CRUD示例:使用PHP+MySQL的相关文章

[MySQL5.6] 一个简单的optimizer_trace示例

[MySQL5.6] 一个简单的optimizer_trace示例 前面已经介绍了如何使用和配置MySQL5.6中optimizer_trace(点击博客),本篇我们以一个相对简单的例子来跟踪optimizer_trace的产生过程. 本文的目的不是深究查询优化器的实现,只是跟踪optimizer trace在优化器的那一部分输出,因此很多部分只是一带而过,对于需要深究的部分,暂时标注为红色,后续再扩展阅读;之前一直没看过这部分代码,理解起来还是比较困难的… 我们以一个简单的表为例过一下opti

通过Knockout.js + ASP.NET Web API构建一个简单的CRUD应用

REFERENCE FROM : http://www.cnblogs.com/artech/archive/2012/07/04/Knockout-web-api.html 较之面向最终消费者的网站,企业级Web应用对用户体验的要求要低一些.不过客户对“用户体验”的要求是“与日俱增”的,很多被“惯坏了”的用户已经不能忍受Postback带来的页面刷新,所以Ajax在企业级Web应用中得到了广泛的应用.企业级Web应用的一个特点是以“数据处理”为主,所以“面向绑定”的Knockout.js 是一

一个简单网络爬虫示例(转载)

在学生时期,可能听到网络爬虫这个词会觉得很高大上,但是它的简单实现可能学生都不难懂. 网络爬虫应用,就是把整个互联网真的就当做一张网,像蜘蛛网那样,应用就像一个虫子,在网上面按照一定的规则爬动. 现在互联网应用最广的就是http(s)协议了,本文例子就是基于使用http(s)协议的,只作为示例,不涉及复杂的算法(实际上是最重要的). 设计思路: 程序入口从一个或多个url开始,通过http(s)获取url的内容,对获取到内容处理,获取内容中需要爬取的信息,获取到内容中的url链接,再重复以上步骤

IDDD 实现领域驱动设计-一个简单的 CQRS 示例

上一篇:<IDDD 实现领域驱动设计-CQRS(命令查询职责分离)和 EDA(事件驱动架构)> 学习架构知识,需要有一些功底和经验,要不然你会和我一样吃力,CQRS.EDA.ES.Saga 等等,这些是实践 DDD 所必不可少的架构,所以,如果你不懂这些,是很难看懂上篇所提到的 CQRS Journey 和 ENode 项目,那怎么办呢?我们可以从简单的 Demo 一点一滴开始. 代码地址:https://github.com/yuezhongxin/CQRS.Sample 说明:一张很丑陋的

tensorflow框架学习(三)—— 一个简单的神经网络示例

一.神经网络结构 定义一个简单的回归神经网络结构: 数据集为(xi,yi),数据的特征数为1,所以x的维度为1. 输入层1个神经元. 隐藏层数为1,4个神经元. 输出层1个神经元. 隐藏层的激活函数为f(x)=x,输出层的激活函数为ReLU 结构图如下: 二.代码示例 相关函数说明: tf.random_normal :用于生成正太分布随机数矩阵的tensor,tensorFlow有很多随机数函数,可以查找官方文档获得. tf.zeros :用于生成0矩阵的tensor,tf.ones可以用来获

一个简单的ServletContextListener示例

ServletContext可以初始化String类型的参数.但是,如果你希望应用初始化参数是一个数据库DataSource呢?上下文参数只能是String.毕竟,你不能把一个Dog对象塞到XML部署描述文件中(事实上,可以用XML表示一个串行化对象,但是在当前的Servlet规范中还没有相关的支持……没准将来会提供).如果你真的想让Web应用的所有部分都能访问一个共享的数据连接,该怎么办?当然可以把这个DataSource查找名放在一个上下文初始化参数里,这也是当前上下文参数最常见的一种用法.

从一个简单的 JPA 示例开始

本文主要讲述 Spring Data JPA,但是为了不至于给 JPA 和 Spring 的初学者造成较大的学习曲线,我们首先从 JPA 开始,简单介绍一个 JPA 示例:接着重构该示例,并引入 Spring 框架,这两部分不会涉及过多的篇幅,如果希望能够深入学习 Spring 和 JPA,可以根据本文最后提供的参考资料进一步学习. 自 JPA 伴随 Java EE 5 发布以来,受到了各大厂商及开源社区的追捧,各种商用的和开源的 JPA 框架如雨后春笋般出现,为开发者提供了丰富的选择.它一改之

一个简单的MapReduce示例(多个MapReduce任务处理)

一.需求 有一个列表,只有两列:id.pro,记录了id与pro的对应关系,但是在同一个id下,pro有可能是重复的. 现在需要写一个程序,统计一下每个id下有多少个不重复的pro. 为了写一个完整的示例,我使用了多job! 二.文件目录 |- OutCount //单Job的,本次试验没有使用到,这里写出来供参考 |- OutCount2 |- OutCountMapper |- OutCountMapper2 |- OutCountReduce |- OutCountReduce2 三.样本

一个简单的多线程示例

项目中要用 到多线程,需求: 论坛发帖,如果是我们的老师用户发帖,会向所有用户发一条信息,提醒用户去看贴.代码这么实现,老师保存文章后,新写一个线程,获取所有的用户,循环插入信息 具体代码: 通过构造把 动态参数传进来,插入到数据库中,就是这么简单. 如何调用: