Correcting teacher:PHPz
Correction status:qualified
Teacher's comments:
PDO预处理语句(prepared statement)机制,是将一条SQL命令向数据库服务器发送一次(此时发送的参数不是实参,是占位符),以后参数发生变化,数据库服务器只需对命令的结构做一次分析就够了。
对于复杂的查询,此过程要花费较长的时间,如果需要以不同参数多次重复相同的查询,那么该过程将大大降低应用程序的速度。通过使用预处理语句,可以避免重复分析/编译/优化周期。简言之,预处理语句占用更少的资源,因而运行得更快
// 预处理机制,sql中的数据使用占位符
// 命名参数占位符,文号参数占位符
预处理能防止SQL注入
// 数据库的操作
require __DIR__ . '/config/connect.php';
$user = json_decode(file_get_contents('php://input'), true);
$uname = $user['username'];
$pwd = sha1($user['password']);
$sql = "select * from user where uname = '{$uname}' and pwd = '{$pwd};";
//echo $sql;
print_r($db->query($sql)->fetchAll());
从以上截图可以得知,用户在前端可以通过输入相关编译码,获取到不可思议的数据。
// 预处理机制,sql中的数据使用占位符
// 命名参数占位符,文号参数占位符
// 预处理sql语句
// $sql = 'INSERT user VALUES(null, :uname, :pwd, :status);';
$sql = 'SELECT * FROM user WHERE uname=? AND pwd=?';
// 预处理要执行的语句,并返回语句对象 (PDOStatement)
$stmt = $db->prepare($sql);
// 将具体的值绑定到占位符参数上
$stmt->bindValue(1,$uname);
$stmt->bindValue(2, $pwd);
if ($stmt->execute())
{
$users = $stmt->fetchAll();
echo json_encode($users);
} else {
die('查询失败:' . $stmt->errorInfo());
}
通过pdo预处理,应用程序只使用预处理语句,可以防止发生SQL注入。
// ! 新增数据
// 预处理机制,sql中的数据使用占位符
// 命名参数占位符,文号参数占位符
// 预处理sql语句
$sql = 'INSERT user VALUES(null, :uname, :pwd, :status);';
// 预处理要执行的语句,并返回语句对象 (PDOStatement)
$stmt = $db->prepare($sql);
// 将具体的值绑定到占位符参数上
$stmt->bindValue(':uname','隔壁老李11');
$stmt->bindValue(':pwd', sha1('123'));
$stmt->bindValue(':status',1);
if ($stmt->execute())
{
// 打印一条sql预处理命令
// $stmt->debugDumpParams();
echo '新增成功,新记录的主键id=' . $db->lastInsertId();
} else {
$stmt->errorInfo();
}
$sql = 'SELECT id,uname FROM user WHERE id > ?';
// 预处理要执行的语句,并返回语句对象 (PDOStatement)
$stmt = $db->prepare($sql);
// 将具体的值绑定到占位符参数上
$stmt->bindValue(1, 10);
if ($stmt->execute())
{
// 返回受上一个SQL语句影响的行数
// 1. 逐条 fetch + while
// 2. 多条 fetchAll + foreach
$users = $stmt->fetchAll();
foreach($users as $user)
{
extract($user);
vprintf("%d: %s\n", [$id,$uname]);
}
} else {
die('查询失败:' . $stmt->errorInfo());
}
// ! 删除数据
$sql = 'delete from user where id = ? ';
if(!stristr($sql, 'where')){
die('禁止无条件删除');
}
// 预处理要执行的语句,并返回语句对象 (PDOStatement)
$stmt = $db->prepare($sql);
$stmt->bindValue(1,5);
if ($stmt->execute())
{
if($stmt->rowCount()>0){
echo '删除成功';
} else {
echo '没有记录被删除';
}
} else {
die('删除失败:' . $stmt->errorInfo());
}
// ! 更新数据
$sql = 'UPDATE user SET status = ? WHERE uname = ? ;';
// 预处理要执行的语句,并返回语句对象 (PDOStatement)
$stmt = $db->prepare($sql);
$stmt->bindValue(1, 2);
$stmt->bindValue(2,'隔壁老李1');
if ($stmt->execute())
{
if($stmt->rowCount()>0){
echo '更新成功' . $stmt->rowCount() . '条数据';
}else {
echo '没有更新数据';
}
}
$sql = 'INSERT user VALUES(null, :uname, :pwd, :status);';
// 将具体的值绑定到占位符参数上
$stmt->bindValue(':uname','隔壁老李11');
$stmt->bindValue(':pwd', sha1('123'));
$stmt->bindValue(':status',1);
$sql = 'SELECT * FROM user WHERE uname=? AND pwd=?';
$stmt->bindValue(1, $uname);
$stmt->bindValue(2, $pwd);