作者

PDO简介

PHP 数据对象 (PDO) 扩展为 PHP 访问数据库定义了一个轻量级的一致接口。PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。 你可以通过 PHPphpinfo() 函数来查看是否安装了 PDO 扩展。

PDO类

类名 作用
PDO::beginTransaction 启动事务
PDO::commit 提交事务
PDO::__construct 创建一个表示数据库连接的 PDO 实例
PDO::errorCode 获取跟数据库句柄上一次操作相关的 SQLSTATE
PDO::errorInfo 返回最后一次操作数据库的错误信息
PDO::exec 执行一条 SQL 语句,并返回受影响的行数
PDO::getAttribute 返回一个数据库连接的属性
PDO::getAvailableDrivers 返回一个可用驱动的数组
PDO::inTransaction 检查是否在一个事务内
PDO::lastInsertId 返回最后插入行的 ID 或序列值
PDO::prepare 准备要执行的 SQL 语句并返回一个 PDOStatement 对象
PDO::query 执行 SQL 语句,返回 PDOStatement 对象,可以理解为结果集
PDO::quote SQL 语句中的字符串添加引号
PDO::rollBack 回滚事务
PDO::setAttribute 设置属性

PDOStatement 类

类名 作用
PDOStatement::bindColumn 绑定一列到一个 PHP 变量
PDOStatement::bindParam 绑定一个参数到指定的变量名
PDOStatement::bindValue 把一个值绑定到一个参数
PDOStatement::closeCursor 关闭游标,使语句能再次被执行
PDOStatement::columnCount 返回结果集中的列数
PDOStatement::debugDumpParams 打印一条 SQL 预处理命令
PDOStatement::errorCode 获取跟上一次语句句柄操作相关的 SQLSTATE
PDOStatement::errorInfo 获取操作相关的扩展错误信息
PDOStatement::execute 执行一条预处理语句
PDOStatement::fetch 从结果集中获取一行
PDOStatement::fetchAll 返回一个包含结果集中所有行的数组
PDOStatement::fetchColumn 从结果集中的下一行返回单独的一列
PDOStatement::fetchObject 获取下一行并作为一个对象返回
PDOStatement::getAttribute 检索一个语句属性
PDOStatement::getColumnMeta 返回结果集中一列的元数据
PDOStatement::rowCount 返回上一条 SQL 语句查询的行数
PDOStatement::setAttribute 设置语句属性
PDOStatement::setFetchMode 为语句设置默认的获取模式

这里我们以 PHP 原生项目开发为例,使用 PDO 连接数据库和实现 CURD

连接数据库

try {
    $pdo = new PDO('mysql:dbname=chat;host=localhost', 'root', 'root', array(PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8")); //初始化一个PDO对象
    echo "连接成功<br/>";
} catch (PDOException $e) {
    die ("数据库连接失败!: " . $e->getMessage() . "<br/>");
}

使用PDO获取数据

1、查询

try {
    $query = "select * from article";   // 定义查询语句
    $articles = $pdo->query($query);    // 执行查询

    echo "一共从表中获取到" . $articles->rowCount() . "条记录:\n";  // 获取一共有多少条数据

    while($row=$articles->fetch(PDO::FETCH_ASSOC)){  // 对数据进行循环
        print_r($row);                               // 取出一行的值
    }

//    每次获取一条
//    foreach ($articles as $row) {     // 对数据进行循环
//        echo $row['title'] . "\n";    // 取出每一行的值
//        echo $row['content'] . "\n";
//        echo $row['time'] . "\n";
//    }

//    一次性获取所有  
//    $allRows=$articles->fetchAll(PDO::FETCH_NUM);
//    print_r($allRows);

} catch (PDOException $e) {
    echo $e->getMessage();
    print_r($pdo->errorInfo());
}

2、新增/编辑/删除。这里以新增为举例说明,其他语句类似。

if ($_POST) {
    $title = $_POST['title'];
    $content = $_POST['content'];
    $time = time();

    // 执行新增语句
    $query = "insert into article (title,content,time) values ('$title', '$content', '$time')"; 
    $pdo->query($query);
}

PDO::prepare 预处理

PDOStatement::execute() 方法准备要执行的 SQL 语句,SQL 语句可以包含零个或多个命名(:name) 或问号(?)参数标记,参数在 SQL 执行时会被替换。

预处理 SQL 语句中的参数在使用 PDOStatement::execute() 方法时会传递真实的参数。

1、使用命名(:name) 参数来准备 SQL 语句:

$sql = 'select title, content, view from article where view > :view and time = :time';
$result = $pdo->prepare($sql);
$result->execute(array(':view' => 0, ':time' => '1565752403'));
$articles = $result->fetchAll();
print_r($articles);exit;

2、使用问号(?) 参数来准备 SQL 语句

$result = $pdo->prepare('select title, content, view from article where view > ? and time = ?');
$result->execute(array('0', '1565752403'));
$articles = $result->fetchAll();
print_r($articles);exit;

bindParam() 和 bindValue() 实现预处理

1、bindParam() 绑定一个PHP变量到用作预处理的SQL语句中的对应命名占位符或问号占位符, 此变量作为引用被绑定,并只在 PDOStatement::execute() 被调用的时候才取其值。对于使用命名占位符的预处理语句,应是类似 :name 形式的参数名。对于使用问号占位符的预处理语句,应是以1开始索引的参数位置。

$title = '今天学习留言板';
$s = $pdo->prepare('SELECT title FROM article WHERE title = :title');
$s->bindParam(':title', $title); // use bindParam to bind the variable
$s->bindParam(':title', '今天学习留言板');  // 错误
$title = '明天学习函数';
$s->execute(); // 将执行 WHERE title = '明天学习函数'

2、bindValue() 绑定一个值到用作预处理的 SQL 语句中的对应命名占位符或问号占位符。对于使用命名占位符的预处理语句,应是类似 :name 形式的参数名。对于使用问号占位符的预处理语句,应是以1开始索引的参数位置。

$title = '今天学习留言板';
$s = $pdo->prepare('SELECT title FROM article WHERE title = :title');
$s->bindValue(':title', $title); // use bindValue to bind the variable's value
$s->bindValue(':title', '今天学习留言板');  // 正确
$title = '明天学习函数';
$s->execute(); // 将执行 WHERE title = '今天学习留言板'

以上两种方法唯一的区别就是前者使用一个PHP变量绑定参数,而后者使用一个值。所以使用 bindParam 第二个参数只能用变量名,而不能用变量值,而 bindValue 可以使用具体值。

事务处理

事务通常是使多条语句同时执行生效的操作。通俗地讲,在一个事务中执行的任何操作,即使是分阶段执行的,也能保证安全地应用于数据库,并在提交时不会受到来自其他连接的干扰。

如果需要执行一个事务,必须用 PDO::beginTransaction() 方法来启动。一旦开始了事务,可用 PDO::commit()PDO::rollBack() 来完成。举例说明:

try {
    $pdo->beginTransaction();   // 开启事务 
    $pdo->exec("insert into article (title, content, time) values ('哈哈哈', '呵呵呵', time())");   // 新增文章
    $pdo->exec("insert into category (name) values ('长乐未央')");    // 新增分类
    $pdo->commit();    // 提交事务
} catch (Exception $e) {
    $pdo->rollBack();   // 如果有错误,事务回滚并提示错误信息
    echo "失败: " . $e->getMessage(); 
}

PDOStatement类的封装

比如,你想封装一个查询多条和单条的类,可以做如下封装:

/***
 * 查询多条
 * @param $sql
 * @return array
 */
function all($sql)
{
    global $pdo;
    $array = [];
    $result = $pdo->query($sql);
    while ($row = $result->fetch()) {
        $array[] = $row;
    }

    return $array;
}

/***
 * 查询单条
 * @param $sql
 * @return array|null
 */
function one($sql)
{
    global $pdo;
    $result = $pdo->query($sql);
    return $result->fetch();
}

然后查询的时候直接调用即可。

总结:

1、本次课程主要讲解了如果使用 PDO 连接数据库

2、PDO 预处理查询

3、事务处理的用法

4、如何封装 PDOStatement类

注:PDO 类和 PDOStatement 类的区别

1、 PDO 直接调用 query 方法后,返回的是有一个 PDOStatement 对象,可用该对象中 fetchfetchall 等方法操作结果集。

2、PDO 先调用 prepare 方法,返回的也是一个 PDOStatement 对象,他代表一个预处理语句,这时并未执行该 sql 语句,在调用 PDOStatement::execute() 方法才真正执行。

转载请注明,来自https://itfun.tv/news/162