PHP数据库拓展之PDO使用总结:
PDO(PHP Data Object)是PHP的数据对象,它为PHP访问数据库提供了一种兼容一致的轻量级接口,也就是提供了一个数据库访问抽象层,不管使用哪种数据库,都可以使用相同的API来访问和操作数据,大大降低了不同数据库操作的维护工作;另外,PDO提供了对SQL的预编译功能,使执行相同的SQL不需要每次重新加载和编译,可以很好的解决SQL编译性能问题。PDO拓展本身不提供任何数据库功能,须使用具体数据库PDO驱动来访问数据库服务。
· 拓展的作用
· 安装与配置
· 预定义常量
· 连接及操作
· 错误及处理
1、拓展的作用
NOTE:
Php Api:PDO封装及兼容的供php进程调用的数据库访问接口;
Pdo Interface:PDO驱动层关于PDO拓展的接口实现及逻辑处理;
2、安装与配置
A、PDO拓展
PDO在PHP5.0及以前是作为一个PECL拓展使用,而在PHP5.1及后续版本已附带PDO拓展,对于前者,我们可以查看关于PECL拓展安装文章《PHP安装、配置及拓展总结》,地址:
http://blog.csdn.net/why_2012_gogo/article/details/51120645
对于后者,我们只需要启用对应数据库类型的PDO驱动即可,请继续往下看PDO驱动。
B、PDO驱动
这里以PDO_MYSQL(支持数据库版本3.x/4.x/5.x)驱动为例进行说明(同样适合PHP5.0及以前版本),具体如下(我的PHP为5.6.20,源码包ext中已经带有PDO驱动):
$cd php-5.6.20/ext/pdo_mysql
$sudo phpize
$sudo ./configure
--with-php-config=/usr/local/bin/php-config --with-pdo-mysql=/usr/local/mysql
$sudo make
$sudo make install
PDO驱动位置:
Installing shared extensions:
/usr/local/lib/php/extensions/no-debug-non-zts-20131226/pdo_mysql.so
C、PDO配置
php.ini:
[pdo]
extension=/usr/local/lib/php/extensions/no-debug-non-zts-20131226/pdo_mysql.so
NOTE:
配置后,重启PHP服务,例如:fpm、apache等
D、验证安装
<?php
phpinfo();
?>
结果:
说明我们已经安装好了PDO_MYSQL驱动,默认PDO_SQLITE已经添加了。
3、预定义常量
自PHP 5.1及后续版本起,开始使用PHP类常量,之前版本使用类似PDO_PARAM_BOOL这样的全局常量,接下来继续介绍下一些常用的PDO预定义常量:
A、数据类型
//布尔数据类型
PDO::PARAM_BOOL(integer)
//整型数据类型
PDO::PARAM_INT(integer)
//字符串数据类型 SQL中的CHAR,VARCHAR及其它字符串类型
PDO::PARAM_STR(integer)
//NULL数据类型
PDO::PARAM_NULL
//大对象数据类型
PDO::PARAM_LOB
B、获取方式
//指定存储过程的INOUT参数
PDO::PARAM_INPUT_OUTPUT(integer)
//将结果集每一行作为一个对象返回,对象的属性名对应列名,
//但在PDOStatement::fetchAll() 中无效
PDO::PARAM_LAZY(integer)
//将结果集中的每一行作为一个属性名对应列名的对象返回
PDO::PFETCH_OBJ(integer)
//指定获取方式,返回 TRUE 且将结果集中的列值分配给通过//PDOStatement::bindParam() 或PDOStatement::bindColumn() 方法绑定的 PHP 变//量
PDO::FETCH_BOUND(integer)
NOTE:
至于其他的预定义常量,可参看文档:
http://php.net/manual/zh/pdo.constants.php
4、连接及操作
PHP使用PDO连接到数据库,是通过建立PDO实例进行的,不论使用哪种驱动程序,都是使用PDO类名构建,PDO构造函数接受用于指定数据源(DSN)以及用户名和密码。
A、连接
为了方便,这里创建了一个PDO连接和管理的封装类,方便维护和拓展:
class PDOEntity {
private $_dsn = 'mysql:host=localhost;dbname=study';
private $_user = 'root';
private $_pass = '';
private $_dbh = null;
function __construct() {
if(null ==$this->_dbh) {
try {
$this->_dbh= new \PDO(
$this->_dsn,
$this->_user,$this->_pass,
array(\PDO::ATTR_PERSISTENT=>true) // 持久化连接
);
} catch(\PDOException$e) {
print 'Error:'.$e->getMessage().'</br>';
die();
}
}
}
public function getDsn(){
return $this->_dsn;
}
public function getUser(){
return $this->_user;
}
public function getPass(){
return $this->_pass;
}
public function getDbh(){
return $this->_dbh;
}
public function clearDbh(){
$this->_dbh = null;
}
}
B、连接操作
<?php
// 提供一个对外访问PDO的函数(单例模式)
private function getPDOEntity(){
$pdoEntity = null;
if(null ==$pdoEntity) {
$pdoEntity = new PDOEntity();
}
return $pdoEntity;
}
?>
NOTE:
PDO的连接实际就是通过创建PDO实例连接的,这里也就是间接通过创建PDOEntity来连接的,如上面的getPDOEntity即为连接操作。
B、操作
这里以查询为例说明其使用:
<?php
$pdo = $this->getPDOEntity();
try {
// 查询id=1的记录
$statement = 'SELECTid,account,nickname,email,address FROM t_user_info WHERE id=?';
$stmt = $pdo->getDbh()->prepare($statement);
// 执行sql及替换占位符
if($stmt->execute(array($_GET['id']))){
//echo$stmt->debugDumpParams();exit;
// 返回值变量绑定
$stmt->bindColumn('id',$id);
$stmt->bindColumn('account',$account);
$stmt->bindColumn('nickname',$nickname);
$stmt->bindColumn('email',$email);
$stmt->bindColumn('address',$address);
// 显示打印
while ($stmt->fetch()){
echo 'id:'.$id.'---account:'.$account.'---nickname:'.$nickname.'---email:'.$email.'---address:'.$address;
}
} else {
echo '预处理语句执行失败!';
}
} catch(\PDOException$e) {
print 'Error:'.$e->getMessage().'</br>';
die();
} finally {
// 关闭PDO
$this->clearDbh();
}
?>
NOTE:
bindColumn:将返回的结果,以列名形式绑定到变量。
5、错误
如果应用程序不在 PDO 构造函数中捕获异常,zend 引擎采取的默认动作是结束脚本并显示一个回溯跟踪,此回溯跟踪可能泄漏完整的数据库连接细节,包括用户名和密码。因此有责任去显式(通过catch 语句)或隐式(通过set_exception_handler())地捕获异常。
NOTE:
PDO相关的api使用,这里不能全部列出,具体可参考:
http://php.net/manual/zh/refs.database.abstract.php
技术讨论群:
489451956(新)