PDO简介
PHP
数据对象 (PDO) 扩展为 PHP
访问数据库定义了一个轻量级的一致接口。PDO
提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。
你可以通过 PHP
的 phpinfo()
函数来查看是否安装了 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
对象,可用该对象中 fetch
,fetchall
等方法操作结果集。
2、PDO
先调用 prepare
方法,返回的也是一个 PDOStatement
对象,他代表一个预处理语句,这时并未执行该 sql
语句,在调用 PDOStatement::execute()
方法才真正执行。