欢迎,来自IP地址为:44.201.97.138 的朋友
PHP PDO由于语句支持预处理,所以在开发PHP应用时就可以提供更高的安全性。语句预处理是指在SQL语句中使用特定用户输入的语句模板,这个模板中包含了用于变量值替换的点位符。采用这种方式处理SQL语句,不仅让PHP处理SQL语句更加容量,并且可以有效的防止SQL注入攻击(由于PHP PDO在执行SQL语句前会自动忽略其它字符的引用)。
PDO同时支持命名点位符和匿名点位符,同时,点位符只能用在字段值,而不能应用于SQL语句的其它部分,例如字段名或操作符。
使用预处理语句同SQL服务器间存在两次交互,第一次是让SQL语句生效,第二次是将变量值传递给点位符。
1、PHP PDO使用简介
本步骤将使用PHP PDO进行一些基本操作,包括使用PDO连接数据库、执行简单的SQL语句以及高效的显示错误信息等。
1.1 连接数据库
为使用PHP PDO,我们只需要创建一个PDO对象就完成了数据库的连接。当然,在创建这个对象之前,我们需要给出数据库类型、主机名、数据库名、数据库用户名以及数据库用户密码等。
首先,我们先创建一个 DSN 数据源变量,用于指定数据库类型为”mysql”、主机名为”localhost”以及数据库名为”demo”。然后使用PDO创建一个新的数据库对象,完成数据库连接,示例如下:
$dsn = 'mysql:host=localhost;dbname=demo'; $db = new PDO($dsn, 'root', '');
在这里,示例设置的数据库用户为”root”,并且密码为空,可以根据实际情况进行设置。方便起见,将以上代码保存为”pdo-connect.php”,方便其它代码使用。
1.2 PHP PDO的第一条SQL语句
这里,将使用PDO对象执行第一条SQL语句,并且使用PHP print_r函数将取得的结果打印出来。为了程序可以顺利执行,首先使用以下语句在MySQL数据库中添加一些数据:
USE DEMO; CREATE TABLE tb_Daehub ( id INT NOT NULL, first_name VARCHAR(255) NOT NULL, last_name varchar(255) not null, gender varchar(255) NOT NULL, age varchar(255) not null, email_id varchar(255) not null, PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO TB_DAEHUB VALUES (1,'Dae','hub','male','20','mail@daehub.com'),(2,'Ru','ltr','female','22','mail@rultr.com');
现在就可以调用pdo对象的”query”方法来执行查询语句,并将结果集返回给”$row”变量。示例程序如下:
require_once 'pdo-connect.php'; $sql = "SELECT * FROM tb_daehub"; $rows = $db->query($sql);
产生的结果集将每条记录转换为既包含下标又包含”字段名”的数组,可以使用”foreach”循环来遍历,示例代码如下:
foreach ($rows as $row) { echo "<pre>"; print_r($row); echo "</pre>"; }
程序执行结果如下图所示:
1.3 使用PHP PDO的错误处理
如果之前的代码里连接的数据库不存在,那么程序在执行SQL语句时会报错,显示代码在哪里有问题。为了能够得到正确的错误信息,我们可以使用”try-catcht”结构来捕获错误信息。我们可以使用”setAttribute”或者”errorInfo”方法,下面将对两种方法分别进行示例。捕获的错误被分配给变量”$e”,然后就可以使用其”getMseeage”方法获得具体错误信息。如果产生了错误,那么就会在浏览器中显示具体的错误信息。
使用”setAttribute”:
try{ require_once 'pdo-connect.php'; $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "SELECT * FROM tb_error"; $rows = $db->query($sql); } catch(Exception $e){ $error = $e->getMessage(); } if(isset($error)){echo "Errors : ". $error;}
使用”errorInfo”
try { require_once 'pdo-connect.php'; $sql = "SELECT * FROM tb_error"; $rows = $db->query($sql); $errorInfo = $db->errorInfo(); print_r($errorInfo); echo '</br>'; if(isset($errorInfo[2])){ $error = $errorInfo[2]; } } catch (Exception $e) { $error = $e->getMessage(); } if(isset($error)){echo "Errors : ". $error;}
根据查看”errorInfo”的内容,可以发现具体的错误信息被保存在下标为2的错误信息数组中,于是使用”$errorInfo[2]”来显示具体内容。代码的执行结果如下图所示:
2、使用PHP PDO获取数据
现在我们将深入了解如何使用PDO对象从数据库中获取数据,并且我们将尝试使用不同的方法。首先将了解如何使用”fetch”方法,然后是”fetchall”方法,最后了解如何使用”fetchcolumn”以及”rowcount”方法来获得特定记录。
2.1 使用”fetch”方法
在PDO中,”fetch”方法将从结果集中获得一条记录的数值,如果想获得多条记录,那么需要使用循环来实现。”while”循环是同”fetch”方法配合最为常用的。以下是使用”while”循环来获得数据的示例代码:
require_once 'pdo-connect.php'; $sql = "SELECT * FROM tb_Daehub"; $result = $db->query($sql); while($row = $result->fetch()){ echo "<pre>"; print_r($row); echo "</pre>"; }
程序执行后的结果如之前的示意图所示,可以看到,结果集中既包含数值下标型数据也包含键值对型数据,可以通过设置”fetch”方法的类型参数来指定获取数值型还是字符型结果。关于”fetch”的类型参数将在最后讲解。
2.2 使用”fetchall”方法
“fetchall”方法将获得SQL语句的所有内容作为结果集,之后就可以使用手环来遍历结果集中的内容,也可以直接查看,示例代码如下:
require_once 'pdo-connect.php'; $sql = "SELECT * FROM tb_daehub"; $result = $db->query($sql); $all = $result->fetchAll(); echo "<pre>"; print_r($all); echo "</pre>";
程序执行结果如下图所示:
可以看到,”fetchall”返回的结果是一个二维数组,同”fetch”方法的执行结果略有区别。
2.3 使用”fetchColumn”方法获得特定字段的数值
“fetchColumn”方法用于返回特定字段(也就是某一列)的数值,并且只返回一条数据。如果不指定方法的参数,则”fetchColumn”默认返回结果集中第一个字段的数值。
注意”fetchColumn”接收的参数是结果集字段序号值而不是字段名,以下示例将返回email字段的数据:
require_once 'pdo-connect.php'; $sql = "SELECT * FROM tb_daehub"; $result = $db->query($sql); while ($col = $result->fetchColumn(5)){ echo "Email : ". $col . "<br>"; }
2.4 计算PDO结果集的数量
在PDO中可以使用”rowCount”方法来计算结果集的数量,使用示例如下:
require_once 'pdo-connect.php'; $sql = "SELECT * FROM tb_daehub"; $result = $db->query($sql); $count = $result->rowCount(); echo $count;
3、使用PDO增加和删除记录
3.1 使用”query”方法插入数据
首先,我们直接使用SQL语句插入记录,执行完SQL语句后,我们直接用”var_dump”打印出结果:
require_once 'pdo-connect.php'; $sql = "INSERT INTO TB_DAEHUB VALUES(3,'daehub','rultr','male','42','daehub@rultr.com');"; $result = $db->query($sql); var_dump($result);
执行结果如下所示:
可以看到,程序会将SQL语句显示出来,事实上调用完”query”方法时,记录已经插入完成,而使用”query”方法时不会得到SQL语句的执行结果。为了可以更好的跟踪SQL执行过程,可以使用”exec”方法来替代”query”方法来获取执行结果。
3.2 使用”exec”方法插入数据
使用之前的”query”方法,我们不能确切知道SQL语句的执行结果,现在,我们使用”exec”方法来重新编码执行插入的代码:
require_once 'pdo-connect.php'; $sql = "INSERT INTO TB_DAEHUB VALUES(3,'daehub','rultr','male','42','daehub@rultr.com');"; $result = $db->exec($sql); var_dump($result);
此时,程序执行完后会将语句执行后的结果反馈回来。此处如果执行成功,则返回受影响的数量,这里会显示1。
3.3 得到最后一个插入记录的ID
使用”lastInsertID”方法可以得到插入记录后的ID值,示例代码如下:
$db->lastInsertID();
3.4 使用PDO删除刻录
使用PDO删除记录同插入记录类似,就是将SQL语句改为删除语句,然后使用”exec”方法执行,最后查看程序执行的结果,示例代码如下:
require_once 'pdo-connect.php'; $sql = "DELETE FROM TB_DAEHUB WHERE ID = 3;"; $result = $db->exec($sql); var_dump($result);
如果SQL语句删除执行正确,则返回1,而删除错误则返回0。
3.5 “query”和”exec”方法的使用场合
“query”方法同”exec”方法的区别在于”query”方法可以用于”SELECT”语句,可以返回结果集;而”exec”方法则适合用于其它”INSERT”、”DELETE”和”UPDATE”的SQL语句场合,用于得到实际影响的记录数量。
4、预处理语句介绍:数值绑定
预处理语句使用点位符来表示接收外部的数据,例如表单中提交的数据。可以把数据同点位符通过”bindParam”或者”bindValue”方法进行绑定。
PDO支持使用全名或匿名参数来绑定数值,我们介绍如何使用命名或匿名参数来进行绑定。当然,也可以通过一个数组来进行数值传递。
使用预处理语句执行单条查询时会同服务器进行两次交互,首先验证和优化SQL语句,然后将数值发送给点位符,并得到结果。
4.1 数据绑定的不同方法
可以使用”bindParam”或者”bindValue”方法来将数值绑定到点位符。
“bindParam”方法同一个变量同时工作,你不能通过表达式例如计算或者字符串连接来绑定变量。这是由于绑定的变量直到执行时才会变量数值,换句话说,我们绑定的是变量而不是变量的数值。
“bindValue”方法会立即绑定数值,所以这个数值必须是确知的,我们甚至可以使用”bindValue”方法来设置一个字段为NULL。
4.2 使用占位符
这里,将讲解如何使用命名占位符,为了理解方便,采用”INSERT”语句,当然也可以使用”DELETE”或”UPDATE”语句。
首先,需要将点位符放置于SQL语句中,这个具有名字的点位符使用”:firstname, :lastname, :email, :gender, :age”形式,然后使用”prepare”方法预处理SQL语句,之后进行外部数据的绑定,最后使用”exec”方法执行SQL语句,以下是示例代码:
$lastName = 'Rultr'; $gender = 'Male'; $age = '44'; $email ='daehub@rultr.com'; require_once 'pdo-connect.php'; $sql = "INSERT INTO TB_DAEHUB VALUES(:id, :firstname, :lastname, :gender, :age , :email)"; $result = $db->prepare($sql); $result->bindValue(':id',3); $result->bindValue(':firstname', 'Daehub'); $result->bindParam(':lastname', $lastName); $result->bindParam('gender',$gender); $result->bindParam('age',$age); $result->bindParam('email',$email); $res = $result->execute(); var_dump($res);
程序执行结果如下:
可以看到,程序将返回SQL语句是否执行成功,这是一个布尔值,可以方便用于其它条件。
4.3 使用匿名点位符
匿名点位符同命名点位符正好相反,它将使用”?”来当点位符,然后使用占位符序号来绑定数据,最后执行SQL语句。示例代码如下:
$lastName = 'Rultr'; $gender = 'Male'; $age = '44'; $email ='daehub@rultr.com'; require_once 'pdo-connect.php'; $sql = "INSERT INTO TB_DAEHUB VALUES(?, ?, ?, ?, ?, ?)"; $result = $db->prepare($sql); $result->bindValue(1,3); $result->bindValue(2, 'Daehub'); $result->bindParam(3, $lastName); $result->bindParam(4,$gender); $result->bindParam(5,$age); $result->bindParam(6,$email); $res = $result->execute(); var_dump($res);
执行结果同命名占位符一样,也是返回一个布尔值来表示语句是否执行成功。
4.4 关联数组点位符
关联数组是命名占位符的一种推荐方式,可以在预处理语句中使用关联数组。这样,我们就可以在数据绑定时使用关联数组,示例代码如下:
require_once 'pdo-connect.php'; $sql = "INSERT INTO TB_DAEHUB VALUES(:id, :firstname, :lastname, :gender, :age , :email)"; $result = $db->prepare($sql); $values = array(':id' => 3, ':firstname' => 'Daehub', ':lastname' => 'Rultr', ':gender' => 'Male', ':age' => '44', ':email' => 'daehub@rultr.com' ); $res = $result->execute($values); var_dump($res);
4.5 匿名占位符使用数组
使用”?”号的匿名占位符,可以使用数组来进行进行数据绑定,示例代码如下:
require_once 'pdo-connect.php'; $sql = "INSERT INTO TB_DAEHUB VALUES(?, ?, ?, ?, ?, ?);"; $result = $db->prepare($sql); $values = array( 3, 'Daehub', 'Rultr', 'Male', '44', 'daehub@rultr.com' ); $res = $result->execute($values); var_dump($res);
4.6 绑定输出结果
预处理语句同样可以用于绑定输出结果集,可以使用”bindColumn”方法将结果集的字段同变量进行绑定,然后通过循环将变量的值分别打印出来,示例代码如下:
require_once 'pdo-connect.php'; $sql = "SELECT * FROM TB_DAEHUB"; $result = $db->prepare($sql); $result->execute(); $result->bindColumn('first_name', $fname); $result->bindColumn('last_name', $lname); $result->bindColumn('id', $id); $result->bindColumn('email_id', $email); while($row = $result->fetch()){ echo $fname ." ". $lname ." ". $id ." ". $email."<br>"; }