具體參考《PHP核心技術與最佳實踐》的5.1章 《什么是PDO》
1. PDO的介紹PHP針對每種數據庫都有一個獨立的模塊、一組獨立的函數。這樣的結構和設計讓PHP兼容多種數據庫變得困難。一旦要將一個應用移到另外一種數據庫環境中,或者是需要添加新的數據庫支持,就不得不重新編寫和數據庫相關的操作。通常編寫多個類,用適配器模式來實現。在這個歷史背景下PDO出現了。PDO(PHP Data Objects)提供了一個通用接口訪問多種數據庫,即抽象的數據模型支持連接多種數據庫。有了PDO使代碼變得更簡潔、更安全。
在PHP中,連接MySQL數據庫的通常有3種方式:
MySQL系列函數:最常用,是過程式風格的一組應用(不建議,在PHP7.0已廢除)
MySQLi系列函數:是MySQL函數的增強改進版,提供了過程化和面向對象兩種風格的API,增加了預編譯和參數綁定等新的特性
PDO:從語法上講,PDO更接近MySQLi
具體的可以參考:【連接數據庫】PHP7的連接數據庫的三種方法【原創】
相比MySQLi,PDO的優勢在于支持多種數據庫,而MySQLi只能支持MySQL,所以一般更推薦使用PDO來對數據庫進行操作。
PDO提供了一個數據訪問抽象層,這就意味著不管使用哪種數據庫,都可以用同樣一組API對數據進行操作,保證了可抽象性和訪問接口的一致性。
開啟PDO很容易,一般來說安裝好PHP默認都會開啟PDO,如果沒有則去php.ini中找到以下語句,把前面的分號去掉即可
;extension=php_pdo.dll2. PDO的使用
使用PDO的第一步是配置數據源,之后的用法和MySQL擴展操作數據庫的方法沒有什么區別了,
PDO的操作主要有PDO::query()、PDO::exec()、PDO::prepare()
PDO::query():主要是用于有記錄結果返回的操作,特別是SELECT操作
PDO::exec():主要是針對沒有結果集合返回的操作,比如INSERT、UPDATE、DELETE等操作,它返回的結果是當前操作影響的列數
PDO::prepare():主要是預處理操作,需要通過$rs->execute()來執行預處理里面的SQL語句,這個方法可以綁定參數,功能比較強大
以下是PDO的示例:
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $db->exec("SET NAMES "UTF8""); // 插入到日志中 $sql = "INSERT INTO users(name, email, password, created_at) values ("pdo_test", "8888@qq.com", "bbb", now())"; $db->exec($sql); // 使用預處理語句 $insert = $db->prepare("INSERT INTO users(name, email, password, created_at) values (?, ?, ?, now())"); $insert->execute(array("pdo_test1", "8448657@qq.com", "aaa")); // 異常 $insert->execute(array("pdo_test2", "8448657@qq.com", "aaa", 9, 10)); $sql = "select name, email, password, created_at from users"; $query = $db->prepare($sql); $query->execute(); var_dump($query->fetchAll(PDO::FETCH_ASSOC)); } catch (PDOException $e) { echo $e->getMessage(); }
注意:使用PDO從MySQL數據庫查詢出來的數據都是string類型的,在某些特殊應用下,可能需要轉換格式
3. PDO的參數綁定和預編譯PDO最大的特點就是引入參數綁定和預編譯。
下面是從數據庫中查詢某條記錄:
query("SELECT name FROM users WHERE id = " . $_GET["id"]);
這是一段糟糕的代碼。插入一個原始的請求參數到 SQL 請求中。這將讓被黑客輕松地利用[SQL 注入]方式進行攻擊。想一下如果黑客將一個構造的 id 參數通過像 http://domain.com/?id=1%3BDEL... 這樣的 URL 傳入。這將會使 $_GET["id"] 變量的值被設為 1;DELETE FROM users 然后被執行從而刪除所有的 user 記錄!因此,你應該使用 PDO 限制參數來過濾 ID 輸入。
上面的代碼可優化為:
prepare("SELECT name FROM users WHERE id = :id"); $id = filter_input(INPUT_GET, "id", FILTER_SANITIZE_NUMBER_INT); $stmt->bindParam(":id", $id, PDO::PARAM_INT); $stmt->execute();
在MySQL應用中,為了防止注入攻擊,通常在PHP中使用intval、addslashes等函數對傳入的參數進行轉義,轉變為SQL中合法的參數類型,這種方法較復雜,而使用PDO的bindParam方法會變得很快捷,只需要在函數中指定第三個參數,即可對傳入的參數進行轉換,轉換為需要的類型拼接到原生的SQL語句中
比如:
prepare("SELECT name, colour, calories FROM fruit WHERE calories > :calories AND colour = :colour"); // 綁定變量,將變量轉化為int類型 $sth->bindParam(":calories", $calories, PDO::PARAM_INT); // 綁定變量,將變量轉化為string類型 $sth->bindParam(":colour", $colour, PDO::PARAM_STR, 12); // 執行 $sth->execute(); var_dump($sth->fetchAll(PDO::FETCH_ASSOC)); // 執行預處理語句(第二種綁定變量的方式) $sth = $db->prepare("SELECT name, colour, calories FROM fruit WHERE calories > ? AND colour = ?"); // 綁定變量,將變量轉化為int類型 $sth->bindParam(1, $calories, PDO::PARAM_INT); // 綁定變量,將變量轉化為string類型 $sth->bindParam(2, $colour, PDO::PARAM_STR, 12); // 執行 $sth->execute(); var_dump($sth->fetchAll(PDO::FETCH_ASSOC));
預編譯負責兩件事,轉義和軟解析提速。程序要支持預編譯,除了要數據庫支持外,還需要驅動支持(PDO和MySQLi均支持)
4. PDO事務處理一個事務中所有的工作在提交時,即使是分階段執行,也要保證安全的應用于數據庫,不被其他的連接干擾,事務工作可以在請求發生錯誤時自動取消。
事務的主要特性:原子性、一致性、獨立性、持久性(Atomicity,Consistency,Isolation,Durability,ACID)。典型運用就是通過把批量的改變保存,然后立即執行,這樣就能提高效率,一旦事務不成功,將會回滾到初始狀態,保證數據的一致性。
SQL通常工作在自動提交模式下,這意味著執行的每個查詢都有自己隱含的事務處理,無論是數據庫支持事務還是因數據庫不支持而不存在事務,DML語句執行的結果都將立即生效而不可更改。比如在MySQL中執行一條update語句,其功能將會立即生效并且是永久性不可更改性的。而在Oracle數據庫中,默認是事務模式,要delete一條數據,數據并不會被永久性刪除,只有執行了commit命令后才會生效。
PDO中使用beginTransaction()方法來創建事務。在一個事務中,使用commit()或者是rollback()方法來結束事務,具體應用哪種方法這取決于事務中代碼運行是否成功。腳本結束或者一個連接要關閉時,如果還有一個未處理完的事務,PDO自動將其回滾。這對于腳本意外終止情況來說是一個安全方案,如果沒有明確提交事務,它將假設發生一些錯誤,為數據的安全執行回滾。
自動回滾僅發生于通過beginTransaction()建立的事務。如果用手動方式執行一個開始事務的查詢,PDO無法知道他的情況故無法回滾。
代碼如下:
beginTransaction(); for($i = 0; $i < 1000000; $i++) { $conn->exec("insert into `users` values(null, "username")"); } // 提交事務 $conn->commit(); } catch(PDOException $ex) { // 執行回滾 $conn->rollBack(); }
注意:因為使用了事務,要么成功要么失敗,如果發現第一條執行了,但是第二條沒有執行或者是失敗了,則應該檢查一下表類型是否為MyISAM,MyISAM引擎是不支持事務的,需要改用InnoDB或者其他的支持事務的引擎。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28206.html
摘要:是什么首先思考為什么選擇是一個數據訪問抽象層抽象是雙重的一個是眾所周知但不太重要的另一個是模糊的但是是最重要的眾所周知為不同的數據庫提供了統一的接口雖然這個功能本身很龐大但是對于固定程序來說不是過于重要的事情基本所有的程序都是使用統一的后端 PDO是什么 首先思考, 為什么選擇PDO PDO 是一個數據訪問抽象層(Database Access Abstraction Layer). ...
閱讀 702·2021-09-29 09:34
閱讀 2554·2019-08-30 15:53
閱讀 3361·2019-08-29 17:17
閱讀 761·2019-08-29 16:08
閱讀 1120·2019-08-29 13:03
閱讀 951·2019-08-27 10:54
閱讀 688·2019-08-26 13:39
閱讀 2859·2019-08-26 13:34