PDO是PHP Data Object(PHP数据对象)的简称,它是与PHP5.1版本一起发布的,目前支持的数据库包括Firebird、FreeTDS、Interbase、MySQL、MS SQL Server、ODBC、Oracle、Postgre SQL、SQLite和Sybase。当操作不同数据库时,只需要修改PDO中的DSN(数据库源) ,即可使用PDO的统一接口进行操作。
PDO支持多种数据库,对于不同的数据库有不同的扩展文件。若要启动对MySQL数据库驱动程序的支持,需要在php.ini配置文件中找到“;extension=php_pdo_mysql.dll”去掉分号注释以开启扩展。修改完成后重新启动Apache,通过phpinfo()函数查看PDO扩展是否开启成功,如图所示。
使用PDO扩展连接数据库,需要实例化PDO类,同时传递数据库连接参数,具体声明方式如下。
PDO::__construct ( string $dsn [, string $username [, string $password [, array $driver_options ]]] )
//设置数据库的DSN信息(数据库类型:主机地址;端口号;数据库名;字符集)
$dsn = 'mysql:host=localhost;port=3306;dbname=itcast;charset=utf8';
try{
$pdo = new PDO($dsn, 'root', '123456');
echo 'PDO 连接数据库成功';
}catch(PDOException $e){
//连接失败,输出异常信息
echo 'PDO连接数据库失败:'.$e->getMessage();
}
上述代码用于实例化PDO时进行数据库连接操作,如果连接发生失败就会抛出PDOException异常信息。通过try包裹可能发生异常的代码,利用catch进行异常处理。当PDOException异常发生时,调用getMessage()方法可以查看错误信息。
另外,PDO构造方法中的第4个参数$driver_options可以用于设置字符集(如果DSN中已经设置了字符集则不需要在此处设置),示例代码如下。
$options = [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8'];
$pdo = new PDO($dsn, 'root', '123456', $options);
上述代码在实例化PDO对象时,把第4个参数添加上,就可以完成对数据库字符集的设置。
PDO 对象中提供了query()和exec()方法,用于执行 SQL 语句:
/通过query()方法执行查询类SQL,如:SELECT
$sql = 'SELECT * FROM `user`';
var_dump($pdo->query($sql)); //输出结果:object(PDOStatement)#2 (1) {……}
//通过exec()执行操作类SQL,如:INSERT、UPDATE、DELETE
$sql = "INSERT INTO `user` (`name`,`password`) VALUES ('小明', '123456')";
var_dump($pdo->exec($sql)); //输出结果:int(1)
需要注意的是,exec()方法不会对SELECT语句返回结果,而使用 query()方法可以获得返回结果。
PDO中常用获取结果集的方式有3种:
fetch()
fetchColumn()
fetchAll()
PDO 中的 fetch()方法可以从结果集中获取下一行数据:
mixed PDOStatement::fetch ([ int $fetch_style [, int $cursor_orientation = PDO::FETCH_ORI_NEXT [, int $cursor_offset = 0 ]]] )
在上述语法中,可选参数$column_number用于设置行中列的索引号,该值从0开始。如果省略该参数,则获取第一列。该方法执行成功则返回单独的一列,失败返回false
若想要获取结果集中所有的行,可以使用 PDO 提供的 fetchAll() 方法
array PDOStatement::fetchAll ([ int $fetch_style [, mixed $fetch_argument [, array $ctor_args = array() ]]] )
在上述语法中, f e t c h s t y l e 参 数 用 于 控 制 结 果 集 中 数 据 的 返 回 方 式 , 默 认 值 为 P D O : : F E T C H B O T H ; 参 数 fetch_style参数用于控制结果集中数据的返回方式,默认值为 PDO::FETCH_BOTH;参数 fetchstyle参数用于控制结果集中数据的返回方式,默认值为PDO::FETCHBOTH;参数fetch_argument根据 f e t c h s t y l e 参 数 的 值 的 变 化 而 有 不 同 的 意 义 , 具 体 如 表 所 示 。 参 数 fetch_style参数的值的变化而有不同的意义,具体如表所示。参数 fetchstyle参数的值的变化而有不同的意义,具体如表所示。参数ctor_args 用于表示当$fetch_style 参数的值为 PDO::FETCH_CLASS 时,自定义类的构造函数的参数。
为了更好的掌握PDO处理结果集的方法,接下来演示
// ① 循环获取所有关联数组结果
$stmt = $pdo->query('SELECT `name`,`password` FROM `user`');
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
echo $row['name'], '---', $row['password'];
}
// ② 获取一列结果
$stmt = $pdo->query('SELECT `name` FROM `user`');
while($name = $stmt->fetchColumn()){
echo $name;
}
// ③ 获取所有结果
$stmt = $pdo->query('SELECT * FROM `user`');
$data = $stmt->fetchAll(PDO::FETCH_ASSOC); //以关联数组返回所有结果
print_r($data);
PDO实现预处理机制的一些常用方法。
prepare()方法
bindParam()方法
execute()方法
PDO提供了prepare()方法执行预处理语句,它返回一个PDOStatement类对象,其语法格式如下。
PDOStatement PDO::prepare ( string $statement [, array $driver_options = array() ] )
在上述声明中,参数 s t a t e m e n t 表 示 预 处 理 的 S Q L 语 句 , 在 S Q L 语 句 中 可 以 添 加 占 位 符 , P D O 支 持 两 种 占 位 符 , 即 问 号 占 位 符 ( ? ) 和 命 名 参 数 占 位 符 ( : 参 数 名 称 ) ; statement表示预处理的SQL语句,在SQL语句中可以添加占位符,PDO支持两种占位符,即问号占位符(?)和命名参数占位符(:参数名称); statement表示预处理的SQL语句,在SQL语句中可以添加占位符,PDO支持两种占位符,即问号占位符(?)和命名参数占位符(:参数名称);driver_options是可选参数,表示设置一个或多个PDOStatement对象的属性值。
bindParam()方法可以将变量参数绑定到准备好的查询占位符上
bool PDOStatement::bindParam ( mixed $parameter , mixed &$variable [, int $data_type = PDO::PARAM_STR [, int $length [, mixed $driver_options ]]] )
在上述语法中,参数 p a r a m e t e r 用 于 表 示 参 数 标 识 符 ; parameter用于表示参数标识符; parameter用于表示参数标识符;variable用于表示参数标识符对应的变量名;可选参数 d a t a t y p e 用 于 明 确 参 数 类 型 , 其 值 使 用 P D O : : P A R A M ∗ 常 量 来 表 示 , 如 表 所 示 ; data_type用于明确参数类型,其值使用PDO::PARAM_*常量来表示,如表所示; datatype用于明确参数类型,其值使用PDO::PARAM∗常量来表示,如表所示;length是可选参数用于表示数据类型的长度。该方法执行成功时返回true,执行失败则返回false。
execute()方法用于执行一条预处理语句,其语法格式如下
bool PDOStatement::execute ([ array $input_parameters ] )
在上述声明中,可选参数$input_parameters表示一个元素个数与预处理语句中占位符数量一样多的数组,用于为预处理语句中的占位符赋值。当占位符为问号占位符(?)时,需为execute()方法传递一个索引数组参数;当占位符为命名参数占位符(:参数名称)时,需为execute()方法传递一个关联数组参数。
为了更好的掌握PDO预处理机制的使用方法,接下来进行演示:
// ① 问号占位符方式
$sql = 'INSERT INTO `user` (`name`,`password`) VALUES (?, ?)';
$stmt = $pdo->prepare($sql);
$stmt->execute(['小明', '123456']);
$stmt->execute(['小红', '123abc']);
// ② 参数占位符方式
$sql = 'INSERT INTO `user` (`name`,`password`) VALUES (:name, :password)';
$stmt = $pdo->prepare($sql);
$stmt->execute(['name'=>'小明', 'password'=>'123456']);
$stmt->execute(['name'=>'小红', 'password'=>'123abc']);
/ ③ 参数绑定方式
$sql = 'INSERT INTO `user` (`name`,`password`) VALUES (:name, :password)';
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':name', $name);
$stmt->bindParam(':password', $password);
$name = '小明';
$password = '123456';
$stmt->execute();
$name = '小红';
$password = '123abc';
$stmt->execute();
PDO扩展可以通过execute()方法直接传入数组,不需要手动指定变量类型,代码更加简洁。
在使用SQL语句操作数据库时,难免会出现各种各样的错误,比如语法错误、逻辑错误等。为此,PDO提供了错误处理机制,能够捕获SQL语句中的错误,并提供了三种方案可以选择。
SILENT模式(默认)
WARNING模式
EXCEPTION模式
“PDO::ERRMODE_SILENT”为PDO默认的错误处理模式。此模式在错误发生时不进行任何操作,只简单的设置错误代码,用户可以通过PDO提供的errorCode()和errorInfo()这两个方法对语句和数据库对象进行检查。如果错误是由于调用语句对象PDOStatement而产生的,那么可以使用这个对象调用这两个方法;如果错误是由于调用数据库对象而产生的,那么可以使用数据库对象调用上述两个方法
在项目的调试或测试期间,如果想要查看发生了什么问题且不中断程序的流程,可以将PDO的错误模式设置为“PDO::ERRMODE_WARNING”。当错误发生时,除了设置错误代码外,PDO还会发出一条E_WARNING信息。
在了解上述三种错误处理模式后,下面通过代码演示如何在程序中进行修改,代码如下。
//设置为SILENT模式
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
//设置为WARNING模式
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
//设置为EXCEPTION模式
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
在默认的SILENT模式中,当通过prepare()执行SQL语句失败,出现错误时不会提示任何信息。
为了更好的理解三种错误处理模式,下面通过代码进行演示,具体如下
上述代码执行后,程序的运行结果如图所示。从图中可以看出,默认情况下PDO不显示错误信息,需要手动判断execute()方法的返回值来获知是否执行成功。
PDO中还提供了许多丰富的方法方便在开发中使用。下表列举了PDO扩展的其他常用操作方法,读者也可以参考PHP手册了解更多内容。
表中,beginTransaction()、commit()和rollback()用于事务处理;rowCount()方法用于返回上一个对应的PDOStatement对象执行DELETE、INSERT、或UPDATE语句受影响的行数。
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
2 //① 开启一个事务
3 $pdo->beginTransaction();
4 try{
5 //执行插入操作
6 $stmt = $pdo->prepare(‘INSERT INTO `user`(`name`,`password`) 7VALUES (?,?)');
7 $stmt->execute(['小明', '123456']);
8 $stmt->execute(['小红', '123abc']);
9 //② 获取最后插入的ID
10 $id = $pdo->lastInsertId();
11 //执行删除操作
12 $stmt = $pdo->prepare('DELETE FROM `user` WHERE `id`>6');
13 $stmt->execute();
14 //③ 获取受影响的行数
15 $count = $stmt->rowCount();
16 }catch(PDOException $e){
17 //④ 执行失败,事务回滚
18 $pdo->rollback();
19 exit($e->getMessage());
20 }
21 //⑤ 提交事务
22 $pdo->commit();
上述代码演示了PDO的事务处理,第3行用于开启一个事务;第22行用于提交一个事务;第18行用于执行失败时,进行事务回滚操作;第10代码返回最后插入的ID号;第15行代返回执行删除操作后受影响的行数。