PDO(php data object)扩展类库为php访问数据库定义了轻量级的、一致性的接口,它提供了一个数据库访问抽象层,这样,无论你使用什么数据库,都可以通过一致的函数执行查询和获取数据,大大简化了数据库的操作,并能够屏蔽不同数据库之间的差异,使用pdo可以很方便地进行跨数据库程序的开发,以及不同数据库间的移植,是将来php在数据库处理方面的主要发展方向,它可以支持mysql,postgresql,oracle,mssql等多种数据库。
PDO安装
1.编辑php.ini文件:
extension=php_pdo.dll
extension=php_pdo_mysql.dll
2.重启apache服务
3.打开phpinfo.php查看是否有pdo
创建PDO对象与连接使用PDO对象
1.创建PDO对象
$dsn = 'mysql:dbname=testdb;host=127.0.0.1'; //连接MySQL数据库的DSN
$user = 'dbuser'; //MySQL数据库的用户名
$password = 'dbpass'; //MySQL数据库的密码
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo '数据库连接失败: ' . $e->getMessage();
}
2.设置连接字符集
设置php连接mysql时的客户端字符串和连接字符串集为:
$pdo->exec(“set names utf8”);
或者:
$pdo->query(“set names utf8”);
3.调整PDO行为
setAttribute() //设置PDO行为属性
getAttribute() //得到PDO行为属性值
4.设置错误处理模式
PDO::ATTR_ERRMODE //错误处理模式
PDO::ERRMODE_SILENT:不报错误(忽略)(0)
PDO::ERRMODE_WARNING:以警告的方式报错(1)
PDO::ERRMODE_EXCEPTION:以异常的方式报错(推荐使用)(2)
设置方式:
在构造时初始化错误模式通过pdo对象的setAttribute()方法设置。
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
面向过程
$con->errorCode():SQL语句错误代码
$con->errorInfo():错误信息
面向对象
捕获PDOException异常对象
5.使用PDO执行SQL语句
exec()方法用于执行有影响行数的语句
query()方法用于执行有结果集的语句
下面是栗子:
//连接数据库 $dsn = 'mysql:dbname=xiaofan;host=localhost'; $username = 'root'; $password = ''; try{ $dbh = new PDO($dsn,$username,$password); }catch(PDOException $e){ echo $e->getMessage(); } $dbh->exec("set names utf8"); //设置php连接mysql时的客户端字符串和连接字符串集 $sql = "insert into users(username,tel) values('xiaoming','123456789')"; $dbh->exec($sql); //执行插入 删除等影响行数的语句,使用exec() $sql = "select username,tel from users"; $query = $dbh->query($sql); //执行查询语句 有结果集的语句,使用query() $result = $query->fetchAll(); //通过一次调用返回所有结果,结果是以数组形式保存 var_dump($result);
以上是简单的PDO执行方法,而实际中我们会使用下面的PDO预处理方法执行SQL语句。
PDO预处理
PDO预处理相比上面的简单方法最大优势是:防止SQL注入漏洞,有利于网站数据的安全。同时,也有利于多次执行。
1.PDOStatement对象的方法
fetch() 返回结果集的下一行,结果指针下移,到头返回false
fetchAll() 通过一次调用返回所有结果,结果是以数组形式保存
execute() 负责执行一个准备好了的预处理语句
rowCount() 返回使用增、删、改、查操作语句后受影响的行总
bindParam() 将参数绑定到相应的查询占位符上
bindColumn() 将查询结果的字段绑定变量
参数: PDO::FETCH_BOTH (default)、PDO::FETCH_ASSOC、 PDO::FETCH_NUM、PDO::FETCH_OBJ、 PDO::FETCH_COLUMN表示取指定某一列如:$rslist = $stmt->fetchAll(PDO::FETCH_COLUMN,2);取第三列数据
2.准备语句
得到pdo预处理对象的方法:
$sql=“select * from user order by id”;
$sth=$pdo->prepare($sql);
以上代码中的$sth即为预处理对象
在PDO中参数式的SQL语句有两种(预处理sql):
insert into stu(id,name) value(?,?); //?号式(适合参数少的)
insert into stu(id,name) value(:id,:name);//别名式(适合参数多的)
3.绑定参数
A.点位符方式
$stmt->bindParam(1, $name, PDO::PARAM_STR);
B.别名方式
$stmt->bindParam(':name', $name);
这里特别注意:不能传入字符串,必须用变量 $stmt->bindParam(':name','xiaofan');这样是错误的
4.执行预处理方式
A.占位符?
$query = "INSERT INTO contactInfo (name, address, phone) VALUES (?, ?, ?)"; $stmt = $dbh->prepare($query);
//传递一个数组为预处理查询中的问号参数绑定值,并执行一次。
$stmt->execute(array("赵某某", "海淀区", "15801688348"));
//再次传递一个数组为预处理查询中的问号参数绑定值,并执行第二次插入数据。 $stmt->execute(array("孙某某", "宣武区", "15801688698"));
B.占位符 :
$query = "INSERT INTO contactInfo (name, address,) VALUES (:name, :address)";
//调用PDO对象中的prepare()方法准备查询,使用命名参数
$stmt = $dbh->prepare($query);
//传递一个数组为预处理查询中的命名参数绑定值,并执行一次。
$stmt->execute(array("name"=>"赵某某","address"=>"海淀区"));
//再次传递一个数组为预处理查询中的命名参数绑定值,并执行第二次插入数据。
$stmt->execute(array("name"=>"孙某某","address"=>"宣武区"));
5.预处理查询
$query = "SELECT uid, name, phone, email FROM contactInfo WHERE
$stmt = $dbh->prepare($query); //准备声明好的一个查询
$stmt->execute(); //执行准备好的查询
$stmt->bindColumn(1, $uid); //通过列位置偏移数绑定变量
$stmt->bindColumn(2, $name); //通过列位置偏移数绑定变量$name
$stmt->bindColumn('phone', $phone); //绑定列名称到变量$phone上
$stmt->bindColumn('email', $email); //绑定列名称到变量$email上
while ($stmt->fetch(PDO::FETCH_BOTH)) {
echo $uid."\t".$name."\t".$phone."\t".$email."\n";
}
下面是栗子:
//连接数据库 $dsn = 'mysql:dbname=xiaofan;host=localhost'; $username = 'root'; $password = ''; try{ $dbh = new PDO($dsn,$username,$password); }catch(PDOException $e){ echo $e->getMessage(); } $dbh->exec("set names utf8"); //设置php连接mysql时的客户端字符串和连接字符串集 //PDO预处理执行 //使用?占位符 $sql = "insert into users(username,tel) values(?,?)"; $stmt = $dbh->prepare($sql); $arr = array('user1',11111111); $stmt->execute($arr); //使用:占位符 $sql = "insert into users(username,tel) values(:username,:tel)"; $stmt = $dbh->prepare($sql); $arr = array("username"=>"user3","tel"=>"333333333"); $stmt->execute($arr); //PDO预处理查询 $sql = "select username,tel from users where id > :id"; $stmt = $dbh->prepare($sql); $stmt->execute(array("id"=>2)); $stmt->bindColumn(1,$username); //通过列位置偏移数绑定变量 $stmt->bindColumn('tel',$tel); //绑定列名称到变量上 //用while循环获取每行内容 while($stmt->fetch(PDO::FETCH_ASSOC)){ echo $username.'--'.$tel.'<br>'; } //也可以直接将结果放入一个数组 $result = $stmt->fetchAll(PDO::FETCH_COLUMN,1); //获取第二列数据,注意是列不是行 var_dump($result); //不使用bindColumn绑定方法 while($result = $stmt->fetch(PDO::FETCH_BOTH)){ echo $result['username'].'--'.$result['tel'].'<br>'; }
PDO事务处理
1.MySQL的事务处理
事务:将多条sql操作(增删改)作为一个操作单元,要么都成功,要么都失败。
MySQL对事务的支持:
被操作的表必须是innoDB类型的表(支持事务)
MySQL常用的表类型:MyISAM(非事务)增删改速度快、InnodB(事务型)安全性高
2.构建事务处理应用程序
开启一次事务:
$pdo->beginTransaction();
提交一次事务:
$pdo->commit();
回滚一次事务:
$pdo->rollback();
注意如下设置:
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0);
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,1);
以下是事务提交的栗子
$db->beginTransaction(); try{ $sql = 'INSERT INTO user(username,tel) values(:username,:password)'; $smt = $db->prepare($sql); $arr = array("username" => "mazi","password" => "963"); if (!$smt->execute($arr)){ throw new PDOException('first error'); } $sql = 'INSERT INTO admin(username,tel) values(:username,:password)'; $smt = $db->prepare($sql); $arr = array("username" => "andy","password" => "951"); if (!$smt->execute($arr)){ throw new PDOException('second error'); } $db->commit(); }catch(PDOException $e){ $db->rollback(); echo $e->getMessage(). '<br>'; }