PDO是 PHP Data Oject 的缩写,即PHP数据对象。提供了访问各种数据库的一致接口,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。
PDO还提供了预处理功能来防止SQL注入,另外也可以使用事务功能。
PHP在安装的时候,已经默认安装了PDO扩展,但要使用PDO操作具体的数据库,需要安装相应的数据库驱动扩展pdo-dbname
。安装扩展的方法这里不做说明。
要查看PDO支持哪些数据库驱动,点击这里:PHP: PDO 驱动 - Manual
下面使用PDO连接本地的MySQL数据库,先实例化一个PDO对象:
$pdo = new PDO('mysql:host=localhost;port=3306;dbname=test;charset=utf8', 'root', '123456');
第一个参数为数据源名称,其中mysql
为数据库名称(小写),:
号后面的参数有:
host
:数据库主机地址,本地可以填localhost
或127.0.0.1
,默认本机。port
:数据库服务端口号,默认端口3306。dbname
:要选择数据库名称,这里可以不写,之后可以用执行use dbname
选择。但注意要有改数据库的操作权限。charset
:传输数据使用的字符集,默认`utf8。第二个参数为连接数据库的用户名,第三个参数为用户密码。
其实还有第四个参数,用来设置连接参数,请参考PHP手册:https://www.php.net/manual/zh/pdo.setattribute.php
如果连接出现错误,将抛出一个 PDOException
异常对象,你可以使用 try-catch
语句捕获它。
执行一条SQL查询很简单:
$sql = "select * from tb_user";
$statement = $pdo->query($sql);
query
方法执行一条SQL语句,查询失败返回false,成功返回一个PDOStatement
对象。
PDOStatement
是PDO语句类,用来获取查询语句结果、执行预处理语句。
先看看执行失败时候如何获取错误信息,PDO类提供两个方法:
// 返回一个SQLSTATE,由5个字母或数字组成的在 ANSI SQL 标准中定义的标识符。
public PDO::errorCode ( void ) : mixed
// 获取最后一个操作相关的错误信息(包含了errorCode,所以一般使用这个)
public PDO::errorInfo ( void ) : array
errorInfo
方法返回的数组结构如下:
元素 | 说明信息 |
---|---|
0 | SQL 错误状态码 |
1 | 驱动指定的错误码 |
2 | 驱动指定的错误信息 |
如果执行的是 select 语句,并且语句执行成功,则可以通过 query()
方法返回的PDOStatement
对象获取查询的结果。PDOStatement类相关的方法有:
// 一般来说如果语句无返回数据使用`rowCount`获取SQL语句影响的行数即可,如insert、delete、update等语句。
public PDOStatement::rowCount() — 返回受上一个SQL语句影响的行数
// 如果有返回数据使用下面的方法,如select语句。
public PDOStatement::columnCount() — 返回结果集中的列数
public PDOStatement::setFetchMode() — 为语句设置默认的获取模式。
public PDOStatement::bindParam() — 绑定一个参数到指定的变量名
public PDOStatement::fetch() — 从结果集中获取下一行
public PDOStatement::fetchAll() — 返回一个包含结果集中所有行的数组
public PDOStatement::fetchColumn() — 从结果集中的下一行返回单独的一列。
public PDOStatement::fetchObject() — 获取下一行并作为一个对象返回。
查看各个函数的具体用法点这里:PHP: PDOStatement - Manual
这里介绍一般获取 select 语句返回数据的用法:
// 设置获取的数据为关联数组(推荐)
$statement->setFetchMode(PDO::FETCH_ASSOC);
// 一行一行的获取
while ($row = $statement->fetch()) {
print_r($row);
}
// 一次全部取出
$rows = $statement->fetchAll();
print_r($rows);
PDO一个强大的功能就是提供了预处理功能,通过先设置SQL语句格式,然后再绑定具体查询参数,可以有效的防止SQL注入攻击。
要使用预处理,先调用PDO对象的prepare()
方法来设置的SQL语句格式,该方法返回一个PDOStatement
对象,接着使用PDOStatement对象的execute()
方法绑定具体的参数并执行查询:
$sql = "select * from tb_user where id = :id and password = :password";
$statement = $pdo->prepare($sql); // 设置SQL语句格式
// 准备查询参数
$args = [
':id' => 1004,
':password' => '123456',
];
$res = $statement->execute($args); // 绑定参数并执行查询
上面使用了名称占位符:id
和:password
,还可以使用通用占位符?
。如果使用了通用占位符,那么绑定的参数的时候不需要指定名称,按顺序传入即可,就像这样:
$sql = "select * from tb_user where id = ? and password = ?";
$statement = $pdo->prepare($sql);
$args = [1004, '123456'];
$res = $statement->execute($args);
还可以不一次性绑定所有参数,而是以一个一个的绑定参数值:
// (1)通过序号绑定
$sql = "select * from tb_user where id = ? and password = ?";
$statement = $pdo->prepare($sql);
$statement->bindValue(1, 1004, PDO::PARAM_INT);
$statement->bindValue(2, '123456', PDO::PARAM_STR);
$res = $statement->execute();
// (2)通过名称占位符绑定
$sql = "select * from tb_user where id = :id and password = :password";
$statement = $pdo->prepare($sql); // 设置SQL语句格式
$statement->bindValue(':id', 1004, PDO::PARAM_INT);
$statement->bindValue(':password', '123456', PDO::PARAM_STR);
$res = $statement->execute();
使用bindValue()
方法可以一个个绑定参数,并且它的第三个参数可以指定参数类型,默认为PDO::PARAM_STR
,要查看全部的类型可以点击这里:PDO预定义常量。
和bindValue()
方法类似的还有bindParam()
方法,它们的参数相同,不同的是变量作为引用被绑定,并只在execute()
被调用的时候才取其值。
execute()
方法会返回一个bool
值表示查询是否成功,如果返回false
你可以使用下面两个方法获取错误信息:
// 返回一个 SQLSTATE,由5个字母或数字组成的在 ANSI SQL 标准中定义的标识符。
public PDOStatement::errorCode ( void ) : mixed
// 获取最后一个操作相关的错误信息(包含了errorCode,所以一般使用这个)
public PDOStatement::errorInfo ( void ) : array
PDO提供了事务功能,相关的方法如下:
// 启动一个事务
public PDO::beginTransaction ( void ) : bool
// 提交一个事务
public PDO::commit ( void ) : bool
// 回滚一个事务
public PDO::rollBack ( void ) : bool
如果底层数据库驱动不支持事务,则beginTransaction()
方法会抛出一个PDOException
异常。
使用例子:
try {
// 开始一个事务,关闭自动提交
$pdo->beginTransaction();
// 开始SQL查询,可以使用预处理
$sth = $pdo->exec("UPDATE dessert SET name = 'hamburger'");
$sql = 'INSERT INTO fruit(name, colour, calories) VALUES (?, ?, ?)';
$sth = $dbh->prepare($sql);
foreach ($fruits as $fruit) {
$sth->execute(array(
$fruit->name,
$fruit->colour,
$fruit->calories,
));
}
// 提交
$pdo->commit();
} catch (Exception $e) { // 发生错误则回滚
$pdo->rollBack();
echo $e->getMessage();
}
// 此时数据库连接恢复到自动提交模式
暂无评论,赶紧发表一下你的看法吧。