PHP操作PDO、预处理以及事务

àì夳堔傛蜴生んèń 2022-04-11 12:49 411阅读 0赞

PDO为PHP访问各类数据库定义了一个轻量级一致性的接口,无论什么数据库,都可以通过一致的方法执行查询和获取数据,而不用考虑不同数据库之间的差异,大大简化了数据库操作。使用PDO可以支持mysql、postgresql、oracle、mssql等多种数据库。

本文以基础讲解常用的PHP以PDO方式操作MySQL,包括常用的CURD语句执行,以及预处理语句和事务的应用。虽然很多朋友使用开发框架封装好了数据库操作层,或者使用ORM等不直接接触SQL语句,但是在一些小项目中可能会用到原生的数据库操作,所以虽然是基础但是很有用。

准备

我们准备一张mysql数据表mycomments,这是一张常见的评论表。

  1. CREATE TABLE `mycomments` (
  2. `id` int(11) NOT NULL,
  3. `post_id` int(10) NOT NULL DEFAULT '0',
  4. `content` varchar(255) NOT NULL,
  5. `user_id` int(10) NOT NULL,
  6. `created_at` datetime NOT NULL
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

连接

首先创建PDO对象,建立与数据库服务器的连接。

  1. $dbhost = '127.0.0.1'; //数据库服务器
  2. $dbport = 3306; //端口
  3. $dbname = 'demo'; //数据库名称
  4. $dbuser = 'root'; //用户名
  5. $dbpass = 'xxxx'; //密码
  6. // 连接
  7. try {
  8. $db = new PDO('mysql:host='.$dbhost.';port='.$dbport.';dbname='.$dbname, $dbuser, $dbpass);
  9. $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //设置错误模式
  10. $db->query('SET NAMES utf8;');
  11. } catch(PDOException $e) {
  12. echo '{"result":"failed", "msg":"连接数据库失败!"}';
  13. exit;
  14. }

PDO::setAttribute()用于设置属性,如上面的代码中就设置了使用异常模式处理错误。

查询

如果我们不使用预处理语句,可以直接使用query()exec()方法执行sql语句。

  1. //查询
  2. $sql = "SELECT id,content,user_id FROM `mycomments` WHERE post_id=2 ORDER BY id DESC";
  3. $db->query($sql);
  4. //更新
  5. $sql = "UPDATE `mycomments` SET content='second...' WHERE id=5";
  6. $db->exec($sql);

而实际开发中我们最常用的是预处理语句,简单的说预处理语句预先将sql命令分析一次,可以多次执行,提高了处理效率,而且能有效防止SQL注入。在执行单个查询时快于直接使用query()exec()的方法,速度快且安全,所以强烈推荐使用预处理语句。

使用预处理语句处理时配套的方法是prepare()execute()

我们用预处理语句来查询符合条件的数据记录:

  1. $sql = "SELECT id,content,user_id FROM `mycomments` WHERE post_id=? ORDER BY id DESC";
  2. $stmt = $db->prepare($sql);
  3. $post_id = 2;
  4. $stmt->bindParam(1, $post_id, PDO::PARAM_INT);
  5. $stmt->execute();
  6. $row = $stmt->fetch();

我们在sql语句中使用问号(?)参数作为占位符,使用bindParam()可以设置绑定参数值。

不过,如果有很多参数需要传递,我们最常用的是这样写:

  1. $sql = "SELECT id,content,user_id FROM `mycomments` WHERE post_id=:post_id ORDER BY id DESC";
  2. $stmt = $db->prepare($sql);
  3. $stmt->execute([
  4. ':post_id' => 2
  5. ]);
  6. $row = $stmt->fetch();

execute()方法中加入参数占位符数组,不使用?占位符可能更直观点。

fetch()返回查询结果中的一行数据,数据以数组形式返回,该方法可以带参数,其中参数默认为PDO::FETCH_BOTH,即返回一个索引为结果集列名和以0开始的列号的数组,而常用的参数PDO::FETCH_ASSOC则返回一个索引为结果集列名的数组。

fetchAll()可以获取结果集中的所有行,并赋给返回的二维数组。和fetch()一样也可以带参数。

如查询表中用户id为2的所有数据,可能会有多行结果:

  1. $sql = "SELECT id,content FROM `mycomments` WHERE user_id=:user_id ORDER BY id DESC";
  2. $stmt = $db->prepare($sql);
  3. $stmt->execute([
  4. ':user_id' => 2
  5. ]);
  6. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

打印$row结果看下,是不是一个二维数组?

插入

最常用的插入数据表的写法,如果有自增长id(一般必须有),使用lastInsertId()可以获取到插入成功后的id。

  1. $sql = "INSERT INTO `mycomments` (post_id,content,user_id,created_at) VALUES (:post_id, :content, :user_id, :created_at)";
  2. $stmt = $db->prepare($sql);
  3. $stmt->execute([
  4. ':post_id' => 2,
  5. ':content' => 'Hello,啦啦啦',
  6. ':user_id' => 21,
  7. ':created_at' => date('Y-m-d H:i:s'),
  8. ]);
  9. $lastid = $db->lastInsertId(); //返回插入成功后的id

更新

使用预处理更新数据,rowCount()返回影响行数,大于0即表示执行成功的记录数。

  1. $sql = "UPDATE `mycomments` SET content=:content WHERE id=:id";
  2. $stmt = $db->prepare($sql);
  3. $stmt->execute([
  4. ':content' => '我的天啊',
  5. ':id' => 6
  6. ]);
  7. echo $stmt->rowCount();//1, 影响行数

删除

对于只有一个参数需要绑定的,可以使用问号?占位符。删除后同样使用rowCount()返回影响行数,大于0表示执行成功。

  1. $sql = "DELETE FROM `mycomments` WHERE id=?";
  2. $stmt = $db->prepare($sql);
  3. $stmt->execute([6]);
  4. echo $stmt->rowCount();//1

事务

事务是确保数据库一致的机制,是一个或一系列的查询,作为一个单元的一组有序的数据库操作。如果组中的所有SQL语句都操作成功,则认为事务成功,事务则被提交。如果在事务的组中只有一个环节操作失败,事务也不成功,则整个事务将被回滚,该事务中所有操作都被取消。事务在开发中也经常用到,因为很多业务过程都包括多个步骤,如果任何一个步骤失败,则所有步骤都不应发生。

值得注意的是,如果要用到事务处理功能,你的MySQL应该使用InnoDB引擎或者其他支持事务的引擎,切不可以使用MyISAM引擎。

来看PDO事务处理实例:

  1. try {
  2. $db->beginTransaction(); //启动事务
  3. $sql1 = "INSERT INTO `mycomments` VALUES (NULL,'1','wahaha','10','2018-07-25 12:12:01')";
  4. $sql2 = "UPDATE `mycomments` SET content='second...' WHERE sid=2";
  5. $sql3 = "INSERT INTO `mycomments` VALUES (NULL,'3','wahaha','30','2018-07-25 12:12:03')";
  6. $db->exec($sql1);
  7. $db->exec($sql2);
  8. $db->exec($sql3);
  9. $db->commit(); //提交事务
  10. } catch (Exception $e) {
  11. $db->rollBack(); //回滚事务
  12. }

上述代码中首先是启动一个事务,然后依次执行三条sql,然后提交事务。细心的同学可能会发现,在第2条sql中查询条件sid=2有误,因为我们在前面创建mycomments表的时候没有sid这个字段,所以在执行到第2条sql时就会出错,这个时候会抛出异常,使用try{}cache(){}语句即可捕获异常,于是就执行了回滚事务rollBack(),而并没有提交事务。换句话说就是上面的代码虽然第一条sql执行完了,但是最终执行不成功,数据库没有任何写入和更新。

后记

以上是笔者在使用PHP操作PDO开发时的总结,由于小项目中经常使用所以整理成文,分享给大家。

接下来我们会有文章讲解使用DB库简化PDO操作以及使用Eloquent ORM模型进行数据库操作,在大型项目中让数据库操作更轻松更规范,敬请关注。

原文链接:https://www.helloweba.net/php/573.html

发表评论

表情:
评论列表 (有 0 条评论,411人围观)

还没有评论,来说两句吧...

相关阅读

    相关 PHPPDO 事务示例

    在本指南中,我们将向您展示如何将事务与 PHP 的 PDO 对象一起使用。 对于那些不知道的人,数据库事务代表一个“块”或一个“单元”工作。 在大多数情况下,这个工作“单元

    相关 php预处理(msqli和PDO

    哎,身为一个穷逼,以前自学在网上找的好几年前的视频,学的mysql,可惜现在已经不适用了,现在更新一下基础知识,本节介绍一个同mysqli中的面向对象和面向过程以及PDO预处理