相關(guān)學習推薦:mysql教程
通過預處理語句進行增刪改查為什么使用預處理語句
關(guān)于預處理語句我們在上篇教程中已經(jīng)簡單介紹過,我們可以將其與視圖模板類比,所謂預處理語句就是預定義的 sql 語句模板,其中的具體參數(shù)值通過占位符替代:
insert into registry (name, value) values (?, ?)insert into registry (name, value) values (:name, :value)然后在后續(xù)真正要執(zhí)行 sql 語句之前,再通過特定 api 方法將具體參數(shù)值與對應占位符進行綁定和映射。就好比定義的視圖模板也是將變量通過特定占位符替代,然后真正渲染時將變量值傳遞進來填充和渲染一樣。
為什么要費這番周折呢?直接用前面演示的 query 方法進行增刪改查操作它不香嗎?呃,那我們接下來來說說預處理語句的好處,或者說為什么要使用預處理語句進行數(shù)據(jù)庫交互,好處有二:
首先,使用預處理語句提前定義的 sql 模板只會解析一次,但可以通過傳遞不同的參數(shù)值執(zhí)行多次,從而避免模板相同的 sql 語句重復分析、編譯和優(yōu)化,提高數(shù)據(jù)庫操作執(zhí)行速度;其次,后期傳遞給預處理語句的參數(shù)值會被底層驅(qū)動進行處理,從而有效避免 sql 注入攻擊。
綜上,從性能和安全角度考慮,推薦使用預處理語句處理數(shù)據(jù)庫的增刪改查操作。
增刪改查示例代碼
接下來,我們基于 pdo 提供的預處理語句 api 實現(xiàn) mysql 數(shù)據(jù)庫的增刪改查操作,我們將通過面向?qū)ο蟮姆绞絹韺崿F(xiàn):
<?phpclass 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 { // 準備預處理語句 $stmt = $this->pdo->prepare($sql); // 獲取當前時間對應的格式化字符串: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(); // 返回插入記錄對應id } catch (pdoexception $e) { printf("數(shù)據(jù)庫插入失敗: %s\\\\n", $e->getmessage()); } } public function select($id) { $sql = 'select * from `post` where id = ?'; try { // 準備預處理語句 $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 { // 準備預處理語句 $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 { // 準備預處理語句 $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 { // 準備預處理語句 $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 實例(從外部傳入),然后將基于預處理語句實現(xiàn)的增刪改查操作分解到對應的類方法中。整體邏輯非常簡單,以 insert 為例,首先通過 pdo 對象的 prepare 方法傳入 sql 模板構(gòu)建預處理語句,該方法返回 pdostatement 對象,接下來,就是調(diào)用