明天这篇文章,咱们来简略的学习一下 PDO 中的预处理语句以及事务的应用,它们都是在 PDO 对象下的操作,而且并不简单,简略的利用都能很容易地实现。只不过大部分状况下,大家都在应用框架,手写的机会非常少。
预处理语句性能
预处理语句就是筹备好一个要执行的语句,而后返回一个 PDOStatement 对象。个别咱们会应用 PDOStatement 对象的 execute() 办法来执行这条语句。为什么叫预处理呢?因为它能够让咱们屡次调用这条语句,并且能够通过占位符来替换语句中的字段条件。相比间接应用 PDO 对象的 query() 或者 exec() 来说,预处理的效率更高,它能够让客户端 / 服务器缓存查问和元信息。当然,更加重要的一点是,占位符的利用能够无效的避免根本的 SQL 注入攻打,咱们不须要手动地给 SQL 语句增加引号,间接让预处理来解决这个问题,置信这一点是大家都学习过的常识,也是咱们在面试时最常见到的问题之一。
// 应用 :name 模式创立一个只进游标的 PDOStatement 对象
$stmt = $pdo->prepare("select * from zyblog_test_user where username = :username", [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]);
var_dump($stmt);
// object(PDOStatement)#2 (1) {// ["queryString"]=>
// string(57) "select * from zyblog_test_user where username = :username"
// }
$stmt->execute([':username' => 'aaa']);
$aUser = $stmt->fetchAll();
$stmt->execute([':username' => 'bbb']);
$bUser = $stmt->fetchAll();
var_dump($aUser);
// array(1) {// [0]=>
// array(8) {// ["id"]=>
// string(1) "1"
// [0]=>
// string(1) "1"
// ["username"]=>
// string(3) "aaa"
// ……
var_dump($bUser);
// array(1) {// [0]=>
// array(8) {// ["id"]=>
// string(1) "2"
// [0]=>
// string(1) "2"
// ["username"]=>
// string(3) "bbb"
// ……
prepare() 办法的第一个参数就是咱们须要执行的 SQL 语句,在这段代码中,咱们应用的是 :xxx 模式的占位符,所以在调用 prepare() 办法返回的 PDOStatement 对象的 execute() 办法时,咱们须要指定占位符的值。在代码中,咱们应用这一条 SQL 语句,通过替换不同的占位符内容,实现了两次查问。
prepare() 办法的第二个参数是为返回的 PDOStatement 对象设置的属性。常见用法是:设置 PDO::ATTR_CURSOR 为 PDO::CURSOR_SCROLL,将失去可滚动的光标。某些驱动有驱动级的选项,在 prepare 时就设置。PDO::ATTR_CURSOR 是设置数据库游标的类型,而 PDO::CURSOR_FWDONLY 的意思是创立一个只进游标的 PDOStatement 对象。此为默认的游标选项,因为此游标最快且是 PHP 中最罕用的数据拜访模式。对于数据库游标的常识大家能够自行查阅相干的内容。
此外,PDOStatement 还能够通过 bindParam() 办法来绑定占位符数据,咱们将在前面学习 PDOStatement 对象相干的文章中持续学习。
接下来,咱们再看一下应用 ? 号占位符来实现查问,? 号占位符在绑定的时候是以下标模式进行绑定的。
// 应用 ? 模式创立一个只进游标的 PDOStatement 对象
$stmt = $pdo->prepare("select * from zyblog_test_user where username = ?", [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]);
$stmt->execute(['aaa']);
$aUser = $stmt->fetchAll();
var_dump($aUser);
// array(1) {// [0]=>
// array(8) {// ["id"]=>
// string(1) "1"
// [0]=>
// string(1) "1"
// ["username"]=>
// string(3) "aaa"
// ……
当然,这种预编译语句不仅限于查问语句,增、删、改都是能够的,而且也都是反对占位符的。在 PHP 中操作数据库的预处理语句 这篇文章中有具体的示例。
事务能力
对于事务想必大家也都有肯定的理解,所以在这里也不介绍具体的概念了,咱们只看看在 PDO 中事务是如何实现的。首先,咱们先看下在没有事务的状况下会产生什么。
$pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)"); // 胜利插入
$pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12)"); // 报错进行整个 PHP 脚本执行
// Fatal error: Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'blog_test.tran_innodb2' doesn't exist
假如这两个表须要同时更新,但第二条语句报错了。在没有事务的状况下,咱们第一条数据是会失常插入胜利的,这并不是咱们须要的后果。在这时,就须要事务能力的帮忙,让咱们可能让两个表要么同时胜利,要么同时失败。
try {
// 开始事务
$pdo->beginTransaction();
$pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)");
$pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12)"); // 不存在的表
// 提交事务
$pdo->commit();} catch (Exception $e) {
// 回滚事务
$pdo->rollBack();
// 输入报错信息
echo "Failed:" . $e->getMessage(), PHP_EOL;
// Failed: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'blog_test.tran_innodb2' doesn't exist
}
首先就是 beginTransaction() 办法,它是用来敞开数据库的主动提交,并启动一个事务,在这个办法之后,只有遇到 commit() 或者 rollBack() 办法后才会敞开这个事务。
commit() 办法就是操作过程中没有出现意外的话,就将在 beginTransaction() 之后的所有数据操作一起打包提交。
rollBack() 是回滚数据,当 beginTransaction() 之后的某一条语句或者代码呈现问题时,回滚之前的数据操作,保障 beginTransaction() 之后的所有语句要么都胜利,要么都失败。
就是这样三个简略的函数,就为咱们实现了整个事务操作。对于事务的深刻学习咱们会在未来深刻地钻研 MySQL 时再进行探讨。在这里咱们须要留神的是,PDO 对象最好指定错误模式为抛出异样,如果不指定错误模式的话,事务中呈现的谬误也不会间接报错,而是返回错误码,咱们须要通过错误码来确定是否提交或回滚。这样远没有异样机制来的简洁直观。
总结
咱们简略的梳理并学习了一下 PDO 中的预处理和事务相干的常识,接下来就要进入 PDOStatement 对象相干内容的学习。PDOStatement 对象就是 PDO 的预处理对象,也就是在日常开发中咱们会接触到的最多的数据操作对象。这块可是重点内容,大家可不能松散了哦!
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/PHP%E4%B8%AD%E7%9A%84PDO%E6%93%8D%E4%BD%9C%E5%AD%A6%E4%B9%A0%EF%BC%88%E4%BA%8C%EF%BC%89%E9%A2%84%E5%A4%84%E7%90%86%E8%AF%AD%E5%8F%A5%E5%8F%8A%E4%BA%8B%E5%8A%A1.php
参考文档:
https://www.php.net/manual/zh/pdo.prepare.php
https://www.php.net/manual/zh/pdo.begintransaction.php
https://www.php.net/manual/zh/pdo.commit.php
https://www.php.net/manual/zh/pdo.rollback.php
各自媒体平台均可搜寻【硬核项目经理】