溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

通過PDO擴展與MySQL數(shù)據(jù)庫交互如何實現(xiàn)增刪改查和數(shù)據(jù)庫事務(wù)

發(fā)布時間:2020-09-10 14:20:12 來源:億速云 閱讀:148 作者:小新 欄目:MySQL數(shù)據(jù)庫

通過PDO擴展與MySQL數(shù)據(jù)庫交互如何實現(xiàn)增刪改查和數(shù)據(jù)庫事務(wù)?這個問題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見到的。希望通過這個問題能讓你收獲頗深。下面是小編給大家?guī)淼膮⒖純?nèi)容,讓我們一起來看看吧!

通過預(yù)處理語句進行增刪改查

為什么使用預(yù)處理語句

關(guān)于預(yù)處理語句我們在上篇教程中已經(jīng)簡單介紹過,我們可以將其與視圖模板類比,所謂預(yù)處理語句就是預(yù)定義的 SQL 語句模板,其中的具體參數(shù)值通過占位符替代:

INSERT INTO REGISTRY (name, value) VALUES (?, ?)
INSERT INTO REGISTRY (name, value) VALUES (:name, :value)

然后在后續(xù)真正要執(zhí)行 SQL 語句之前,再通過特定 API 方法將具體參數(shù)值與對應(yīng)占位符進行綁定和映射。就好比定義的視圖模板也是將變量通過特定占位符替代,然后真正渲染時將變量值傳遞進來填充和渲染一樣。

為什么要費這番周折呢?直接用前面演示的 query 方法進行增刪改查操作它不香嗎?呃,那我們接下來來說說預(yù)處理語句的好處,或者說為什么要使用預(yù)處理語句進行數(shù)據(jù)庫交互,好處有二:

  • 首先,使用預(yù)處理語句提前定義的 SQL 模板只會解析一次,但可以通過傳遞不同的參數(shù)值執(zhí)行多次,從而避免模板相同的 SQL 語句重復(fù)分析、編譯和優(yōu)化,提高數(shù)據(jù)庫操作執(zhí)行速度;
  • 其次,后期傳遞給預(yù)處理語句的參數(shù)值會被底層驅(qū)動進行處理,從而有效避免 SQL 注入攻擊。

綜上,從性能和安全角度考慮,推薦使用預(yù)處理語句處理數(shù)據(jù)庫的增刪改查操作。

增刪改查示例代碼

接下來,我們基于 PDO 提供的預(yù)處理語句 API 實現(xiàn) MySQL 數(shù)據(jù)庫的增刪改查操作,我們將通過面向?qū)ο蟮姆绞絹韺崿F(xiàn):

<?php
class Post
{
    public $id;
    public $title;
    public $content;
    public $created_at;

    /**
     * @var PDO
     */
    protected $pdo;

    public function __construct(PDO $pdo = null)
    {
        if ($pdo != null) {
            $this->pdo = $pdo;
        }
    }

    public function insert($title, $content)
    {
        $sql = 'INSERT INTO `post` (title, content, created_at) VALUES (:title, :content, :created_at)';
        try {
            // 準(zhǔn)備預(yù)處理語句
            $stmt = $this->pdo->prepare($sql);
            // 獲取當(dāng)前時間對應(yīng)的格式化字符串:2020-05-28 13:00:00
            $datetime = date('Y-m-d H:i:s', time());
            // 綁定參數(shù)值
            $stmt->bindParam(':title', $title, PDO::PARAM_STR);
            $stmt->bindParam(':content', $content, PDO::PARAM_STR);
            $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR);
            // 執(zhí)行語句
            $stmt->execute();
            return $this->pdo->lastInsertId();  // 返回插入記錄對應(yīng)ID
        } catch (PDOException $e) {
            printf("數(shù)據(jù)庫插入失敗: %s\n", $e->getMessage());
        }
    }

    public function select($id)
    {
        $sql = 'SELECT * FROM `post` WHERE id = ?';
        try {
            // 準(zhǔn)備預(yù)處理語句
            $stmt = $this->pdo->prepare($sql);
            // 綁定參數(shù)值
            $stmt->bindValue(1, $id, PDO::PARAM_INT);
            // 執(zhí)行語句
            $stmt->execute();
            return $stmt->fetchObject(self::class);  // 以對象方式返回結(jié)果集
        } catch (PDOException $e) {
            printf("數(shù)據(jù)庫查詢失敗: %s\n", $e->getMessage());
        }
    }

    public function selectAll()
    {
        $sql = 'SELECT * FROM `post` ORDER BY id DESC';
        try {
            // 準(zhǔn)備預(yù)處理語句
            $stmt = $this->pdo->prepare($sql);
            // 執(zhí)行語句
            $stmt->execute();
            return $stmt->fetchAll();  // 返回所有結(jié)果集
        } catch (PDOException $e) {
            printf("數(shù)據(jù)庫查詢失敗: %s\n", $e->getMessage());
        }
    }

    public function update($id)
    {
        $sql = 'UPDATE `post` SET created_at = :created_at WHERE id = :id';
        try {
            // 準(zhǔn)備預(yù)處理語句
            $stmt = $this->pdo->prepare($sql);
            $datetime = date('Y-m-d H:i:s', time());
            // 綁定參數(shù)值
            $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR);
            $stmt->bindValue(':id', $id, PDO::PARAM_INT);
            // 執(zhí)行語句
            $stmt->execute();
            return $stmt->rowCount();
        } catch (PDOException $e) {
            printf("數(shù)據(jù)庫更新失敗: %s\n", $e->getMessage());
        }
    }

    public function delete($id)
    {
        $sql = 'DELETE FROM `post` WHERE id = ?';
        try {
            // 準(zhǔn)備預(yù)處理語句
            $stmt = $this->pdo->prepare($sql);
            // 綁定參數(shù)值
            $stmt->bindValue(1, $id, PDO::PARAM_INT);
            // 執(zhí)行語句
            $stmt->execute();
            return $stmt->rowCount();
        } catch (PDOException $e) {
            printf("數(shù)據(jù)庫刪除失敗: %s\n", $e->getMessage());
        }
    }
}

我們構(gòu)建了一個 Post 類,然后在構(gòu)造函數(shù)中初始化 $pdo 實例(從外部傳入),然后將基于預(yù)處理語句實現(xiàn)的增刪改查操作分解到對應(yīng)的類方法中。整體邏輯非常簡單,以 insert 為例,首先通過 PDO 對象的 prepare 方法傳入 SQL 模板構(gòu)建預(yù)處理語句,該方法返回 PDOStatement 對象,接下來,就是調(diào)用該對像的 bindParam 方法綁定具體參數(shù)值,該方法的第一個參數(shù)是占位符,第二個參數(shù)是參數(shù)值,第三個參數(shù)是值類型(對應(yīng)的常量可以在 PDO 預(yù)定義常量中查詢),綁定好參數(shù)后,就可以調(diào)用 PDOStatement 對象的 execute 方法執(zhí)行預(yù)處理語句了。

對于插入操作,可以通過 PDO 對象上的 lastInsertId 方法返回插入記錄的主鍵 ID,對于更新和刪除方法,可以通過 PDOStatement 對象上的 rowCount 方法返回受影響行數(shù)表示是否操作成功。對于查詢操作,可以通過 PDOStatement 對象的 fetch 方法返回單條記錄,也可以通過 fetchObject 方法返回映射到指定類后的對象實例(也是單條記錄),對于多個結(jié)果,可以通過 fetchAll 方法返回。

需要注意的是,在聲明預(yù)處理語句的時候,可以通過 ? 占位符,也可以通過 :name 這種可讀性更好的占位符,然后在綁定參數(shù)時,既可以通過 bindValue 也可以通過 bindParam 方法,兩者傳遞參數(shù)一樣,只是對于 ? 占位符,需要通過數(shù)值序號建立與 SQL 模板的映射(從 1 開始)。

結(jié)合代碼和 PHP 官方文檔理解上面的代碼并不困難,接下來,我們來編寫測試代碼:

// 初始化 PDO 連接實例
$dsn = 'mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8mb4';
$user = 'root';
$pass = 'root';
try {
    $pdo = new PDO($dsn, $user, $pass);
} catch (PDOException $e) {
    printf("數(shù)據(jù)庫連接失敗: %s\n", $e->getMessage());
}

// 測試代碼
$post = new Post($pdo);
// insert
$title = '這是一篇測試文章

以上就是通過PDO擴展與MySQL數(shù)據(jù)庫交互 實現(xiàn)增刪改查實現(xiàn)和數(shù)據(jù)庫事務(wù)的詳細內(nèi)容,更多請關(guān)注億速云其它相關(guān)文章!

感謝各位的閱讀!看完上述內(nèi)容,你們對通過PDO擴展與MySQL數(shù)據(jù)庫交互如何實現(xiàn)增刪改查和數(shù)據(jù)庫事務(wù)大概了解了嗎?希望文章內(nèi)容對大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI