专注于云服务器
VPS主机优惠测评
国内免备案虚拟主机

通过PDO扩展与MySQL数据库交互 实现增删改查实现和数据库事务

通过PDO扩展与MySQL数据库交互 实现增删改查实现和数据库事务

相关学习推荐:mysql教程

通过预处理语句进行增删改查

为什么使用预处理语句

关于预处理语句我们在上篇教程中已经简单介绍过,我们可以将其与视图模板类比,所谓预处理语句就是预定义的 SQL 语句模板,其中的具体参数值通过占位符替代:

INSERT INTO REGISTRY (name, value) VALUES (?, ?) INSERT INTO REGISTRY (name, value) VALUES (:name, :value)

然后在后续真正要执行 SQL 语句之前,再通过特定 API 方法将具体参数值与对应占位符进行绑定和映射。就好比定义的视图模板也是将变量通过特定占位符替代,然后真正渲染时将变量值传递进来填充和渲染一样。

为什么要费这番周折呢?直接用前面演示的 query 方法进行增删改查操作它不香吗?呃,那我们接下来来说说预处理语句的好处,或者说为什么要使用预处理语句进行数据库交互,好处有二:

  • 首先,使用预处理语句提前定义的 SQL 模板只会解析一次,但可以通过传递不同的参数值执行多次,从而避免模板相同的 SQL 语句重复分析、编译和优化,提高数据库操作执行速度;
  • 其次,后期传递给预处理语句的参数值会被底层驱动进行处理,从而有效避免 SQL 注入攻击。

综上,从性能和安全角度考虑,推荐使用预处理语句处理数据库的增删改查操作。

增删改查示例代码

接下来,我们基于 PDO 提供的预处理语句 API 实现 MySQL 数据库的增删改查操作,我们将通过面向对象的方式来实现:

<?php class Post {     public $id;     public $title;     public $content;     public $created_at;      /**      * @var PDO      */     protected $pdo;      public function __construct(PDO $pdo = null)     {         if ($pdo != null) {             $this->pdo = $pdo;         }     }      public function insert($title, $content)     {         $sql = 'INSERT INTO `post` (title, content, created_at) VALUES (:title, :content, :created_at)';         try {             // 准备预处理语句             $stmt = $this->pdo->prepare($sql);             // 获取当前时间对应的格式化字符串:2020-05-28 13:00:00             $datetime = date('Y-m-d H:i:s', time());             // 绑定参数值             $stmt->bindParam(':title', $title, PDO::PARAM_STR);             $stmt->bindParam(':content', $content, PDO::PARAM_STR);             $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR);             // 执行语句             $stmt->execute();             return $this->pdo->lastInsertId();  // 返回插入记录对应ID         } catch (PDOException $e) {             printf("数据库插入失败: %sn", $e->getMessage());         }     }      public function select($id)     {         $sql = 'SELECT * FROM `post` WHERE id = ?';         try {             // 准备预处理语句             $stmt = $this->pdo->prepare($sql);             // 绑定参数值             $stmt->bindValue(1, $id, PDO::PARAM_INT);             // 执行语句             $stmt->execute();             return $stmt->fetchObject(self::class);  // 以对象方式返回结果集         } catch (PDOException $e) {             printf("数据库查询失败: %sn", $e->getMessage());         }     }      public function selectAll()     {         $sql = 'SELECT * FROM `post` ORDER BY id DESC';         try {             // 准备预处理语句             $stmt = $this->pdo->prepare($sql);             // 执行语句             $stmt->execute();             return $stmt->fetchAll();  // 返回所有结果集         } catch (PDOException $e) {             printf("数据库查询失败: %sn", $e->getMessage());         }     }      public function update($id)     {         $sql = 'UPDATE `post` SET created_at = :created_at WHERE id = :id';         try {             // 准备预处理语句             $stmt = $this->pdo->prepare($sql);             $datetime = date('Y-m-d H:i:s', time());             // 绑定参数值             $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR);             $stmt->bindValue(':id', $id, PDO::PARAM_INT);             // 执行语句             $stmt->execute();             return $stmt->rowCount();         } catch (PDOException $e) {             printf("数据库更新失败: %sn", $e->getMessage());         }     }      public function delete($id)     {         $sql = 'DELETE FROM `post` WHERE id = ?';         try {             // 准备预处理语句             $stmt = $this->pdo->prepare($sql);             // 绑定参数值             $stmt->bindValue(1, $id, PDO::PARAM_INT);             // 执行语句             $stmt->execute();             return $stmt->rowCount();         } catch (PDOException $e) {             printf("数据库删除失败: %sn", $e->getMessage());         }     } }

我们构建了一个 Post 类,然后在构造函数中初始化 $pdo 实例(从外部传入),然后将基于预处理语句实现的增删改查操作分解到对应的类方法中。整体逻辑非常简单,以 insert 为例,首先通过 PDO 对象的 prepare 方法传入 SQL 模板构建预处理语句,该方法返回 PDOStatement 对象,接下来,就是调用该对像的 bindParam 方法绑定具体参数值,该方法的第一个参数是占位符,第二个参数是参数值,第三个参数是值类型(对应的常量可以在 PDO 预定义常量中查询),绑定好参数后,就可以调用 PDOStatement 对象的 execute 方法执行预处理语句了。

对于插入操作,可以通过 PDO 对象上的 lastInsertId 方法返回插入记录的主键 ID,对于更新和删除方法,可以通过 PDOStatement 对象上的 rowCount 方法返回受影响行数表示是否操作成功。对于查询操作,可以通过 PDOStatement 对象的 fetch 方法返回单条记录,也可以通过 fetchObject 方法返回映射到指定类后的对象实例(也是单条记录),对于多个结果,可以通过 fetchAll 方法返回。

需要注意的是,在声明预处理语句的时候,可以通过 ? 占位符,也可以通过 :name 这种可读性更好的占位符,然后在绑定参数时,既可以通过 bindValue 也可以通过 bindParam 方法,两者传递参数一样,只是对于 ? 占位符,需要通过数值序号建立与 SQL 模板的映射(从 1 开始)。

结合代码和 PHP 官方文档理解上面的代码并不困难,接下来,我们来编写测试代码:

// 初始化 PDO 连接实例 $dsn = 'mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8mb4'; $user = 'root'; $pass = 'root'; try {     $pdo = new PDO($dsn, $user, $pass); } catch (PDOException $e) {     printf("数据库连接失败: %sn", $e->getMessage()); }  // 测试代码 $post = new Post($pdo); // insert $title = '这是一篇测试文章'; $content = '测试内容: 今天天气不错'; $id = $post->insert($title, $content); echo '文章插入成功: ' . $id . '<br>'; // select $item = $post->select($id); echo '<pre>'; print_r($item); // update $affected = $post->update($id); echo '受影响的行数: ' . $affected . '<br>'; // delete $affected = $post->delete($id); echo '受影响的行数: ' . $affected . '<br>'; // selectAll $items = $post->selectAll(); print_r($items);

初始化一个 PDO 对象实例传入 Post 构造函数,然后依次调用 Post 对象的增删改查方法。在浏览器中访问,打印结果如下:

通过PDO扩展与MySQL数据库交互 实现增删改查实现和数据库事务

我们可以看到 fetchAll 方法默认返回的结果集数组中既包含索引映射,又包含字段名映射,这可以通过设置获取模式来解决,比如要返回 Post 对象数组,可以这么做:

return $stmt->fetchAll(PDO::FETCH_CLASS, self::class);

这样,返回的结果就是这样的了:

通过PDO扩展与MySQL数据库交互 实现增删改查实现和数据库事务

更多模式设置,请参考官方文档中 fetchAll 方法的介绍和示例。

数据库事务

最后,我们再来看看如何通过 PDO 扩展实现数据库事务的提交和回滚,我们已经知道,对于单条 SQL 语句而言,事务提交和回滚是自动完成的,对于 SQL 语句序列(多条 SQL 语句),则需要显式开启事务和提交事务,PDO 对象也为此提供了对应的 API 方法。非常简单,比如我们在 Post 类中新增一个批量插入方法 batchInsert 方法:

public function batchInsert(array $items) {     $sql = 'INSERT INTO `post` (title, content, created_at) VALUES (:title, :content, :created_at)';     try {         // 开启事务         $this->pdo->beginTransaction();         // 准备预处理语句         $stmt = $this->pdo->prepare($sql);         foreach ($items as $item) {             // 绑定参数值             $datetime = date('Y-m-d H:i:s', time());             $stmt->bindParam(':title', $item->title, PDO::PARAM_STR);             $stmt->bindParam(':content', $item->content, PDO::PARAM_STR);             $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR);             // 执行语句             $stmt->execute();         }         $this->pdo->commit(); // 提交事务         return $stmt->rowCount();  // 返回受影响的行数     } catch (PDOException $e) {         $this->pdo->rollBack(); // 回滚事务         printf("数据库批量插入失败: %sn", $e->getMessage());     } }

我们只需要在执行 SQL 序列之前调用 PDO 对象的 beginTransaction 方法开启事务,然后在所有 SQL 语句执行完成后调用 commit 方法提交事务,如果 SQL 执行过程中出错,则在异常处理代码中通过 PDO 对象的 rollBack 方法回滚事务。

为上述方法编写测试代码:

$post = new Post($pdo); $items = [     [         'title' => '这是一篇测试文章111',         'content' => '测试内容'     ],     [         'title' => '这是一篇测试文章222',         'content' => '测试内容'     ],     [         'title' => '这是一篇测试文章333',         'content' => '测试内容'     ], ]; $post->batchInsert($items); $items = $post->selectAll(); print_r($items);

执行这段代码,打印结果中包含新插入的文章数据,则表明事务提交成功:

通过PDO扩展与MySQL数据库交互 实现增删改查实现和数据库事务

小结

关于通过 PDO 扩展与 MySQL 数据库交互,我们就简单介绍到这里,更多细节可以阅读官方文档,相信通过这几个课程的学习,你已经对 MySQL 数据库的基本使用以及如何在 PHP 中连接数据库并进行增删改查有了初步的认知,从下篇教程开始,我们将结合具体实战项目来开发一个现代的 PHP 项目,将之前的学习到的知识点应用到实战中,并且引入一些现代的 PHP 理念对项目进行管理。

想了解更多相关文章,敬请关注php mysql栏目!

以上就是通过PDO扩展与MySQL数据库交互 实现增删改查实现和数据库事务的详细内容,更多请关注名铺123其它相关文章!

赞(0) 打赏
转载请注明出处:晓波笔记 » 通过PDO扩展与MySQL数据库交互 实现增删改查实现和数据库事务
分享到: 更多 (0)
megalayer云服务器

raksmart云服务器

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

晓波笔记-VPS主机,云服务器优惠促销测评

QQ:87304394

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏