百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>数据库> 通过PDO扩展与MySQL数据库交互 实现增删改查实现和数据库事务
分享文章到:

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

发布时间:09/01 来源:未知 浏览: 关键词:

相关学习引荐: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("数据库插入失败: %s\n", $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("数据库查询失败: %s\n", $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("数据库查询失败: %s\n", $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("数据库更新失败: %s\n", $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("数据库删除失败: %s\n", $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("数据库连接失败: %s\n", $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 对象的增删改查办法。在阅读器中拜访,打印结果如下:

-w727

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

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

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

-w505

更多模式设定,请参照 官方文档中 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("数据库大量插入失败: %s\n", $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);

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

-w846

小结

关于通过 PDO 扩展与 MySQL 数据库交互,我们就简便介绍到这里,更多细节可以阅读官方文档,信赖通过这几个课程的学习,你已经对 MySQL 数据库的根本使用乃至怎样在 PHP 中连接数据库并停止增删改查有了初步的认知,从下篇教程开端,我们将结合详细实战项目来开发一个现代的 PHP 项目,将此前的学习到的知识点利用到实战中,并且引入一些现代的 PHP 理念对项目停止治理。

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

以上就是通过PDO扩展与MySQL数据库交互 实现增删改查实现和数据库事务的具体内容,更多请关注百分百源码网其它相关文章!

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有151人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板