一個簡單的CRUD示例:使用PHP+MySQL

一個簡單的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對象
  • 使用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示例代碼_恆馨博客
相關文章
相關標籤/搜索