本文作者:心月

PDO中預處理語句占位符的使用

心月IT博客 2019-03-29
摘要:占位符在php程序中有著非常重要的作用,對數據安全也有著非常重要的意義,通過占位符我們可以有效驗證傳入參數的有效性,從而防止惡意的SQL注入攻擊。

    使用PDO時不使用預處理語句占位符也可以防止SQL注入,我們可以使用quote()方法來防止SQL注入。quote()為輸入的字符串添加引號(如果有需要),并對特殊字符進行轉義,且引號的風格和底層驅動適配。

quote()防注入

    雖然quote()可以通過加引號及對特殊字符處理,但在官方文檔中并不建議用這個方法來防SQL注入

如果使用此函數構建 SQL 語句,強烈建議使用 PDO::prepare() 配合參數構建,而不是用 PDO::quote() 把用戶輸入的數據拼接進 SQL 語句。 使用 prepare 語句處理參數,不僅僅可移植性更好,而且更方便、免疫 SQL 注入;相對于拼接 SQL 更快,客戶端和服務器都能緩存編譯后的 SQL 查詢。


下面來看看預處理語句prepare()占位符的使用

prepare()中的占位符有兩種形式

①冒號‘:’加關鍵字:(建議使用)

<?php 
header('content-type:text/html;charset=utf-8');
$username="testuser1";
$email="[email protected]";
try{
	$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
	$sql='select * from test_pdo where username=:username and email=:email';
	$stm = $pdo->prepare($sql);
	$stm->execute(array(':username'=>$username,':email'=>$email));
	//rowCount 返回受影響的行數
	echo $stm->rowCount();

}catch(PDOException $e){
	echo $e->getMessage();
}

冒號‘:’加關鍵字占位符

②問號‘?’占位符:

<?php 
header('content-type:text/html;charset=utf-8');
$username="testuser1";
$email="[email protected]";
try{
	$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
	$sql='select * from test_pdo where username=? and email=?';
	$stm = $pdo->prepare($sql);
	$stm->execute(array($username,$email));
	//rowCount 返回受影響的行數
	echo $stm->rowCount();

}catch(PDOException $e){
	echo $e->getMessage();
}

問號‘?’占位符

    在使用問號‘?’占位符時,在execute()中的數組參數需要注意參數的順序,要與對應問號一致,比如第一個問號對應的是'username',array()中的第一個也必須是'username'的參數值。


    在上面的占位符介紹案例中,參數是通過execute()綁定并執行的,其實PDO中有另外一個專門綁定參數的方法——bindParam(),bindParam()方法可以一次綁定多次執行sql語句,如果下次的參數值不一樣也只需要重新給定參數值即可,此時的execute()無須傳遞任何參數。

PDOStatement::bindParam ( mixed $parameter , mixed &$variable [, int $data_type = PDO::PARAM_STR [, int $length [, mixed $driver_options ]]] ) : bool

執行成功時返回 TRUE, 或者在失敗時返回 FALSE。

參數說明:

parameter
參數標識符。對于使用命名占位符的預處理語句,應是類似 :name 形式的參數名。對于使用問號占位符的預處理語句,應是以1開始索引的參數位置。
variable
綁定到 SQL 語句參數的 PHP 變量名。
data_type
使用 PDO::PARAM_* 常量明確地指定參數的類型。要從一個存儲過程中返回一個 INOUT 參數,需要為 data_type 參數使用按位或操作符去設置 PDO::PARAM_INPUT_OUTPUT 位。
length
數據類型的長度。為表明參數是一個存儲過程的 OUT 參數,必須明確地設置此長度。
driver_options

在實際使用中,大多數情況下只需給定前兩個或三個參數

①冒號‘:’占位符綁定參數:(建議使用)

<?php 
header('content-type:text/html;charset=utf-8');
try{
	$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');	
	$sql="INSERT test_pdo(username,password,email) VALUES(:username,:password,:email)";
	$stmt=$pdo->prepare($sql);	
	$stmt->bindParam(":username",$username,PDO::PARAM_STR);
	$stmt->bindParam(":password",$password,PDO::PARAM_STR);
	$stmt->bindParam(":email",$email);
	$username='testuser11';
	$password='123456';
	$email='[email protected]';
	$stmt->execute();
	$username='testuser22';
	$password='123456';
	$email='[email protected]';
	$stmt->execute();
	echo $stmt->rowCount();
}catch(PDOException $e){
	echo $e->getMessage();
}

pdo通過 bindParam()綁定參數多次執行

②問號‘?’占位符綁定參數:

<?php 
header('content-type:text/html;charset=utf-8');
try{
	$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');	
	$sql="INSERT test_pdo(username,password,email) VALUES(?,?,?)";
	$stmt=$pdo->prepare($sql);	
	$stmt->bindParam(1,$username,PDO::PARAM_STR);
	$stmt->bindParam(2,$password,PDO::PARAM_STR);
	$stmt->bindParam(3,$email);
	$username='testuser33';
	$password='123456';
	$email='[email protected]';
	$stmt->execute();
	$username='testuser44';
	$password='123456';
	$email='[email protected]';
	$stmt->execute();
	echo $stmt->rowCount();
}catch(PDOException $e){
	echo $e->getMessage();
}

pdo通過 bindParam()綁定參數多次執行

    問號‘?’占位符在使用時需要注意參數順序問題,因此,在實際項目中建議使用冒號‘:’加關鍵字形式的占位符,清楚明了,不易出錯。

文章版權及轉載聲明:

作者:心月 本文地址:http://www.rawkpk.live/other/215.html發布于 2019-10-18
文章轉載或復制請以超鏈接形式并注明出處心月IT博客

分享到:
贊(

發表評論

快捷輸入:

    評論列表 (有 0 條評論,人圍觀)參與討論