PHP開發過程的那些坑(四) ——PDO bindParam函式
阿新 • • 發佈:2022-05-03
PHP開發過程的那些坑(四)——PDO bindParam函式
(原創內容,轉載請註明來源,謝謝)
坑:
bindParam是PDOStatement的一個方法,用於在PDO操作中繫結佔位符的內容,進行替換,是PDO安全性的一大保障。
通常用法如下:(摘自PHP官方文件)
<?php /* 通過繫結的 PHP 變數執行一條預處理語句 */ $calories = 150; $colour = 'red'; $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour'); $sth->bindParam(':calories', $calories, PDO::PARAM_INT); $sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12); $sth->execute(); ?>
可以看到,通過bindParam方法,可以把calories和colour替換成上面的變數。這個對防止sql注入具有重要作用。
但是,最近我遇到的問題是,通常繫結的內容很多個,可以用foreach來實現,我也就寫了一個方法,如下:
//繫結sql(錯誤的方式) private functionbindSql($query, $arrData){ //注:arrData=array(col1=>val1,col2=>val2…) if(empty($arrData)){ returnnull; }else{ foreach($arrDataas $col => $val){ $col= ':'.$col; $query->bindParam($col, $val); } return$query; } }
但是,當我呼叫這個方法時,發現如果arrData只有一個引數時,正常執行,但是當傳入兩個或者以上時,就出問題了,最後繫結的內容全部變成最後一個val了。
經過我多次和原例子比對,發現沒有問題,百思不得其解,只能再次看官方文件,直到我看到了這個人的留言:(摘自PHP官方文件)
瞬間恍然大悟。需要在$val前面加一個取地址符號&。
分析:
再次認真檢視官方文件,發現其對bindParam的定義如下:(摘自官方文件)
bool PDOStatement::bindParam ( mixed $parameter , mixed &$variable [, int $data_type =PDO::PARAM_STR [, int$length [, mixed $driver_options ]]] )
注意檢視第二個引數 mixed &$variable
,發現有個取地址符號。即此引數是引用繫結,在最終執行sql時才會真正被取值。
因此,單條的使用bindParam(包括連續好幾行都是這個,類似官方文件)可以不用取地址符號,因為每次用不同的變數,則取不同的地址。而如果用foreach時,必須使用&符號,否則隨著foreach的迭代,會被取到最後一個內容當作結果。
改進措施:
加上取地址符即可。
//繫結sql(正確的方式)
private functionbindSql($query, $arrData){
//注:arrData=array(col1=>val1,col2=>val2…)
if(empty($arrData)){
returnnull;
}else{
foreach($arrDataas $col => &$val){
$col= ':'.$col;
$query->bindParam($col, $val);
}
return$query;
}
}
——written by linhxx 2017.07.25