本文作者:心月

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="testuser1@qq.com";
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="testuser1@qq.com";
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='testuser11@qq.com';
	$stmt->execute();
	$username='testuser22';
	$password='123456';
	$email='testuser22@qq.com';
	$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='testuser11@qq.com';
	$stmt->execute();
	$username='testuser44';
	$password='123456';
	$email='testuser22@qq.com';
	$stmt->execute();
	echo $stmt->rowCount();
}catch(PDOException $e){
	echo $e->getMessage();
}

pdo通过 bindParam()绑定参数多次执行

    问号‘?’占位符在使用时需要注意参数顺序问题,因此,在实际项目中建议使用冒号‘:’加关键字形式的占位符,清楚明了,不易出错。

文章版权及转载声明:

作者:心月 本文地址:http://www.xinyueseo.com/other/215.html发布于 2019-09-07
文章转载或复制请以超链接形式并注明出处心月IT博客

分享到:
赞(

发表评论

快捷输入:

    评论列表 (有 0 条评论,人围观)参与讨论