您的位置:首页 > 数据库

PDO数据库抽象层

2016-05-13 23:37 274 查看
什么是PDO

为什么要学习PDO

PDO的配置和启用

PDO连接数据库
通过参数的形式连接数据库

通过uri的形式连接数据库

通过配置文件连接数据库

PDO对象的使用
exec方法执行建表操作并插入一条记录

lastInsertId得到最后一次插入记录的id

exec方法执行其他操作exec方法不能用于查询

errorCode和errorInfo查看错误信息

query方法执行查询语句

query方法也可以插入语句但建议用exec方法

prepare和execute执行查询语句

设置数据库连接属性

PDOStatement对象的使用
quote方法防止SQL注入

prepare预处理语句中占位符的使用

bindParam绑定参数
bindParam删除操作

bindValue把一个值绑定到一个参数

bindColumn 绑定参数

fetchColumn 从结果集中的下一行返回单独的一列

debugDumpParams方法打印一条预处理语句

nextRowset在一个多行集语句句柄中推进到下一个行集

PDO事务处理
PDO错误处理模式

PDO事务处理

用PDO封装数据库操作类
PDO效率剖析

封装PDO数据库操作类

什么是PDO

PHP Data Object (PHP 数据对象)

数据库访问抽象层

用于统一各种数据库的访问接口

为什么要学习PDO

PDO特性:

编码一致性

灵活性

高性能

面向对象

PDO的配置和启用

1.配置PHP.ini文件,开启相应扩展

extension = php_pdo.dll


2.开启对相应数据库的扩展

extension=php_pdo_mysql.dll


3.通过查看phpinfo查看PDO扩展的详细信息

配置完后需要重启PHP-FPM让其重新加载配置文件和生效

service php-fpm restart


PDO连接数据库

通过参数的形式连接数据库(建议用第一种比较好用)

通过uri的方式连接数据库

通过配置文件连接数据库

通过参数的形式连接数据库

<?php
//通过参数形式连接数据库
try{
//dsn 即data source name  数据源
$dsn='mysql:host=localhost;dbname=test';
$username='root';
$passwd='root';
$pdo=new PDO($dsn, $username, $passwd);
var_dump($pdo);
}catch(PDOException $e){
echo $e->getMessage();
}


通过uri的形式连接数据库

<?php
//通过uri的形式连接数据库
try{
$dsn='uri:file://H:\wamp\PHPnow-1.5.6.1428396605\htdocs\pdo\dsn.txt';
$username='root';
$passwd='root';
$pdo=new PDO($dsn,$username,$passwd);
var_dump($pdo);
}catch(PDOException $e){
echo $e->getMessage();
}


dsn.txt

mysql:dbname=test;host=localhost


通过配置文件连接数据库

先在php.ini中配置,然后重启apache加载配置,如下所示

[PHP]
;在php.ini中配置,然后重启apache加载配置
pdo.dsn.test="mysql:host=localhost;dbname=test"
;;;;;;;;;;;;;;;;;;;
; About php.ini   ;
;;;;;;;;;;;;;;;;;;;


<?php
/**
*通过配置文件链接数据库
*在php.ini中配置,然后重启apache加载配置
*/
try{
$dsn='test';
$username='root';
$passwd='root';
$pdo=new PDO($dsn,$username,$passwd);
var_dump($pdo);
}catch(PDOException $e){
echo $e->getMessage();
}


PDO对象的使用

exec()方法执行建表操作并插入一条记录

<?php
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
//exec():执行一条sql语句并返回其受影响的记录的条数,如果没有受影响的记录,他返回0
//exec对于select没有作用
$sql=<<<EOF
CREATE TABLE IF NOT EXISTS user(
id INT(10) UNSIGNED AUTO_INCREMENT KEY,
username VARCHAR(20) NOT NULL UNIQUE,
password CHAR(32) NOT NULL,
email VARCHAR(30) NOT NULL
);
EOF;
$res=$pdo->exec($sql);
var_dump($res);
$sql='INSERT user(username,password,email) VALUES("king","'.md5('king').'","imooc@qq.com")';
//echo $sql;
$res=$pdo->exec($sql);
echo $res;
}catch(PDOException $e){
echo $e->getMessage();
}


lastInsertId得到最后一次插入记录的id

<?php
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
//exec():执行一条sql语句并返回其受影响的记录的条数,如果没有受影响的记录,他返回0
//exec对于select没有作用
//插入多条记录
//  $sql=<<<EOF
//  INSERT user(username,password,email) VALUES("king1","king1","imooc1@qq.com"),
//  ("king2","king2","imooc1@qq.com"),
//  ("king3","king2","imooc1@qq.com")
//
//EOF;
//echo $sql;
$sql='INSERT user(username,password,email) VALUES("king6","king6","imooc6@qq.com")';
$res=$pdo->exec($sql);
echo '受影响的记录的条数为:'.$res,'<br/>';
//$pdo->lastInsertId():得到新插入记录的ID号
echo '最后插入的ID号为'.$pdo->lastInsertId();
if(!$res)
throw new PDOException("<br/>插入数据失败");
}catch(PDOException $e){
echo $e->getMessage();
}


exec()方法执行其他操作,exec()方法不能用于查询

<?php
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
//$sql='update user set username="king" where id=1';
//$sql='delete from userwhere id=1';
$sql='select * from user';
$res=$pdo->exec($sql);
//echo $res.'条记录被影响';
var_dump($res);
//  echo '<hr/>';
//  echo $pdo->lastInsertId();
}catch(PDOException $e){
echo $e->getMessage();
}


errorCode()和errorInfo()查看错误信息**

<?php
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='delete from user12 where id=1';
$res=$pdo->exec($sql);
//echo $res.'条记录被影响';
//var_dump($res);
if($res===false){
//$pdo->errorCode():SQLSTATE的值
echo $pdo->errorCode();
echo '<hr/>';
//$pdo->errorInfo():返回的错误信息的数组,数组中包含3个单元
//0=>SQLSTATE,1=>CODE,2=>INFO
$errInfo=$pdo->errorInfo();
print_r($errInfo);
}
//  echo '<hr/>';
//  echo $pdo->lastInsertId();
}catch(PDOException $e){
echo $e->getMessage();
}


query()方法执行查询语句

<?php
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
//$sql='select * from user where id=2';
$sql='select id,username,email from user';
//$pdo->query($sql),执行SQL语句,返回PDOStatement对象
$stmt=$pdo->query($sql);
var_dump($stmt);
echo '<hr/>';
foreach($stmt as $row){
//print_r($row);
echo '编号:'.$row['id'],'<br/>';
echo '用户名:'.$row['username'],'<br/>';
echo '邮箱:'.$row['email'],'<br/>';
echo '<hr/>';
}
}catch(PDOException $e){
echo $e->getMessage();
}


query()方法也可以插入语句,但建议用exec()方法

<?php
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=imooc','root','root');
$sql='INSERT user(username,password,email) VALUES("king11","'.md5('king11').'","imooc11@qq.com")';
$stmt=$pdo->query($sql);
var_dump($stmt);
}catch(PDOException $e){
echo $e->getMessage();
}


prepare()和execute()执行查询语句

fetch()方法使用

<?php
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='select * from user where username="king11"';
//prepare($sql):准备SQL语句
$stmt=$pdo->prepare($sql);
//execute():执行预处理语句
$res=$stmt->execute();
//var_dump($res);
//fetch():得到结果集中的一条记录
$row=$stmt->fetch();
print_r($row);

//var_dump($stmt);
}catch(PDOException $e){
echo $e->getMessage();
}


setFetchMode()方法和fetchAll()方法使用

<?php
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='select * from user';
$stmt=$pdo->prepare($sql);
$res=$stmt->execute();
//  if($res){
//      while($row=$stmt->fetch(PDO::FETCH_OBJ)){
//          print_r($row);
//          echo '<hr/>';
//      }
//  }
//  $rows=$stmt->fetchAll(PDO::FETCH_ASSOC);
//  print_r($rows);
echo '<hr/>';
$stmt->setFetchMode(PDO::FETCH_ASSOC); //设置返回结果集的模式
//var_dump($stmt);
$rows=$stmt->fetchAll();
print_r($rows);
}catch(PDOException $e){
echo $e->getMessage();
}


设置数据库连接属性

<?php
/**
*getAttribute() 检索一个语句属性
*setAttribute()设置一个语句属性
*/
header('content-type:text/html;charset=utf-8');
try{
$dsn='mysql:host=localhost;dbname=test';
$username='root';
$passwd='root';
$pdo=new PDO($dsn, $username, $passwd);
echo '自动提交:'.$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);
echo '<br/>';
echo 'PDO默认的错误处理模式:'.$pdo->getAttribute(PDO::ATTR_ERRMODE);
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);
echo '<br/>';
echo '自动提交:'.$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);
}catch(PDOException $e){
echo $e->getMessage();
}


批量获取和设置PDO连接属性

<?php
/**
*批量获取PDO属性
*/
header('content-type:text/html;charset=utf-8');
try{
$dsn='mysql:host=localhost;dbname=test';
$username='root';
$passwd='root';
$pdo=new PDO($dsn, $username, $passwd);
$attrArr=array(
'AUTOCOMMIT','ERRMODE','CASE','PERSISTENT','TIMEOUT','ORACLE_NULLS',
'SERVER_INFO','SERVER_VERSION','CLIENT_VERSION','CONNECTION_STATUS'
);
foreach($attrArr as $attr){
echo "PDO::ATTR_$attr: ";
echo $pdo->getAttribute(constant("PDO::ATTR_$attr")),'<br/>';
}
}catch(PDOException $e){
echo $e->getMessage();
}


<?php
header('content-type:text/html;charset=utf-8');
try{
$dsn='mysql:host=localhost;dbname=imooc';
$username='root';
$passwd='root';
$options=array(PDO::ATTR_AUTOCOMMIT=>0,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION);
$pdo=new PDO($dsn, $username, $passwd, $options);
echo $pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);
echo '<br/>';
echo $pdo->getAttribute(PDO::ATTR_ERRMODE);
}catch(PDOException $e){
echo $e->getMessage();
}


PDOStatement对象的使用

quote()方法防止SQL注入

下方的例子用简单登录模块演示:

login.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</head>
<body>
<form action='doAction.php' method='post'>
用户名:<input type='text' name='username' /><br/>
密码:<input type='password' name='password'/><br/>
<input type='submit' value='登陆'/>
</form>
</body>
</html>


doAction.php

<?php
header('content-type:text/html;charset=utf-8');
$username=$_POST['username'];
$password=$_POST['password'];
try{
echo $username;
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');

//下方SQL是有存在SQL注入问题的。当用户在用户名中输入 ' or 1=1 # 时,会返回所有结果
//当然如果php.ini开启了magic_quotes_gpc 则会自动转义,但是不建议这样使用
$sql="select * from user where username='{$username}' and password='{$password}'";
echo $username;
echo $sql;
//通过quote():返回带引号的字符串,过滤字符串中的特殊字符
// $username=$pdo->quote($username);//转义特殊字符串
//$sql="select * from user where username={$username} and password='{$password}'";
echo $sql;
$stmt=$pdo->query($sql);
//PDOStatement对象的方法:rouCount():对于select操作返回的结果集中记录的条数,
//对于INSERT、UPDATE、DELETE返回受影响的记录的条数
echo $stmt->rowCount();
}catch(PDOException $e){
echo $e->getMessage();
}


常用的过滤用户输入的三种方法

1、addslashes

2、mysql_real_escape_string

3、开启php.ini中的魔法引号magic_quotes_gpc (不建议使用)

但是以上三种都不是好的解决办法,参考文档

prepare()预处理语句中占位符的使用

login.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</head>
<body>
<form action='doAction1.php' method='post'>
用户名:<input type='text' name='username' /><br/>
密码:<input type='password' name='password'/><br/>
<input type='submit' value='登陆'/>
</form>
</body>
</html>


doAction1.php

<?php
/*
*预处理语句中第一种占位符的使用
*/
header('content-type:text/html;charset=utf-8');
$username=$_POST['username'];
$password=$_POST['password'];
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql="select * from user where username=:username and password=:password";
$stmt=$pdo->prepare($sql);
$stmt->execute(array(":username"=>$username,":password"=>$password));
echo $stmt->rowCount();

}catch(PDOException $e){
echo $e->getMessage();
}


doAction2.php

login.php用上方的,action改成doAction2.php即可

<?php
/*
*预处理语句中第二种占位符的使用 ?
*/
header('content-type:text/html;charset=utf-8');
$username=$_POST['username'];
$password=$_POST['password'];
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql="select * from user where username=? and password=?";
$stmt=$pdo->prepare($sql);
$stmt->execute(array($username,$password));
echo $stmt->rowCount();

}catch(PDOException $e){
echo $e->getMessage();
}


bindParam()绑定参数

<?php
/**
*bindParam()绑定一个参数到指定的变量名
*/
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
//写预处理语句,推荐使用命名参数占位符的方式,不要使用?号占位符
//?号占位符的索引默认是从1开始的,采用索引的方式不利于代码阅读

//============命名参数占位符方式============
$sql="INSERT user(username,password,email) VALUES(:username,:password,:email)";
$stmt=$pdo->prepare($sql);
$stmt->bindParam(":username",$username,PDO::PARAM_STR);//指定类型
$stmt->bindParam(":password",$password,PDO::PARAM_STR);
$stmt->bindParam(":email",$email);
//============?占位符方式============
// $sql="INSERT user(username,password,email) VALUES(?,?,?)";
// $stmt=$pdo->prepare($sql);
// $stmt->bindParam(1,$username,PDO::PARAM_STR);//指定类型
// $stmt->bindParam(2,$password,PDO::PARAM_STR);
// $stmt->bindParam(3,$email);
//=========================
$username='imooc2';
$password='imooc2';
$email='imooc2@imooc.com';
$stmt->execute();
$username='MR.KING2';
$password='MR.KING2';
$email='MR.KING2@imooc.com';
$stmt->execute();
echo $stmt->rowCount();
}catch(PDOException $e){
echo $e->getMessage();
}


bindParam()删除操作

<?php
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='DELETE FROM user WHERE id<:id';
$stmt=$pdo->prepare($sql);
$stmt->bindParam(":id",$id,PDO::PARAM_INT);
$id = 3;//删除id小于3的记录
$stmt->execute();
echo $stmt->rowCount();
}catch(PDOException $e){
echo $e->getMessage();
}


bindValue()把一个值绑定到一个参数

<?php
/**
*bindValue()把一个值绑定到一个参数
*/
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='INSERT user(username,password,email) VALUES(?,?,?)';
$stmt=$pdo->prepare($sql);
$username='imooc_king';
$password='imooc_king';
//参数标识符。对于使用命名占位符的预处理语句,应是类似 :name 形式的参数名。对于使用问号占位符的预处理语句,应是以1开始索引的参数位置。
$stmt->bindValue(1,$username);
$stmt->bindValue(2,$password);
$stmt->bindValue(3,'imooc@imooc.com');
$stmt->execute();
echo $stmt->rowCount();
$username='imooc_king1';
$password='imooc_king1';
$stmt->bindValue(1,$username);
$stmt->bindValue(2,$password);
$stmt->execute();
echo $stmt->rowCount();
}catch(PDOException $e){
echo $e->getMessage();
}


bindColumn 绑定参数

<?php
//bindColumn  绑定一列到一个 PHP 变量
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='SELECT username,password,email FROM user';
$stmt=$pdo->prepare($sql);
$stmt->execute();
//返回结果集中的列数,不是行数
echo '结果集中的列数一共有:'.$stmt->columnCount();
echo '<hr/>';
//getColumnMeta此函数是实验性的。此函数的表象,包括名称及其相关文档都可能在未来的 PHP 发布版本中未通知就被修改。使用本函数风险自担 。
//print_r($stmt->getColumnMeta(0));
echo '<hr/>';
//bindColumn  绑定一列到一个 PHP 变量
//这里总共三列(username,password,email),索引从1开始
//如下
$stmt->bindColumn(1, $username);
$stmt->bindColumn(2,$password);
$stmt->bindColumn(3, $email);
//PDO::FETCH_BOUND:返回 TRUE ,并分配结果集中的列值给 PDOStatement::bindColumn() 方法绑定的 PHP 变量。
while($stmt->fetch(PDO::FETCH_BOUND)){
echo '用户名:'.$username.'-密码:'.$password.'-邮箱:'.$email.'<hr/>';
}
}catch(PDOException $e){
echo $e->getMessage();
}


fetchColumn — 从结果集中的下一行返回单独的一列

<?php
//fetchColumn — 从结果集中的下一行返回单独的一列。
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='SELECT username,password,email FROM user';
$stmt=$pdo->query($sql);
echo $stmt->fetchColumn(0),'<br/>';
echo $stmt->fetchColumn(1),'<br/>';
echo $stmt->fetchColumn(2);
}catch(PDOException $e){
echo $e->getMessage();
}


debugDumpParams()方法打印一条预处理语句

?号占位符方式打印

<?php
//debugDumpParams()方法打印一条预处理语句
//?号占位符方式
try{

$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='INSERT user(username,password,email) VALUES(?,?,?)';
$stmt=$pdo->prepare($sql);
$stmt->bindParam(1, $username,PDO::PARAM_STR);
$stmt->bindParam(2,$password,PDO::PARAM_STR);
$stmt->bindParam(3,$email,PDO::PARAM_STR);
$username='testParam';
$password='testParam';
$email='testParam@imooc.com';
$stmt->execute();
$stmt->debugDumpParams();
}catch(PDOException $e){
echo $e->getMessage();
}


命名参数占位符方式打印

<?php
//debugDumpParams()方法打印一条预处理语句
//命名参数占位符方式
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='SELECT * FROM user WHERE username=:username AND password=:password';
$stmt=$pdo->prepare($sql);
$stmt->bindParam(':username', $username,PDO::PARAM_STR);
$stmt->bindParam(':password',$password,PDO::PARAM_STR);
$username='testParam';
$password='testParam';
$stmt->execute();
$stmt->debugDumpParams();
}catch(PDOException $e){
echo $e->getMessage();
}


nextRowset在一个多行集语句句柄中推进到下一个行集

先创建一个存储过程,获取两个结果集

CREATE TABLE IF NOT EXISTS userAccount(
id TINYINT UNSIGNED AUTO_INCREMENT KEY,
username VARCHAR(20) NOT NULL UNIQUE,
money DECIMAL(10,2)
)ENGINE=INNODB;

INSERT userAccount(username,money) VALUES('imooc',10000),('king',5000);
#创建一个存储过程
DELIMITER //#定界符
CREATE PROCEDURE test1()
BEGIN
SELECT * FROM user;
SELECT * FROM userAccount;
END
//#定界符结束
DELIMITER ;#恢复定界符


获取多个结果集中的下一个结果集

<?php
//nextRowset
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='call test1()';
$stmt=$pdo->query($sql);
$rowset=$stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($rowset);//只获取到了第一个结果集
echo '<hr color="red"/>';
//想获取多个结果集中的下一个结果集
$stmt->nextRowset();//在一个多行集语句句柄中推进到下一个行集
$rowset=$stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($rowset);
}catch(PDOException $e){
echo $e->getMessage();
}


PDO事务处理

PDO错误处理模式

<?php
/*
PDO::ERRMODE_SLIENT:默认模式,静默模式
PDO::ERRMODE_WARNING:警告模式
PDO::ERRMODE_EXCEPTION:异常模式---推荐使用
*/
try{
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
//$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql='SELECT * FROM noneTable';
$pdo->query($sql);
echo $pdo->errorCode();
echo '<br/>';
print_r($pdo->errorInfo());
}catch(PDOException $e){
echo $e->getMessage();
}


PDO事务处理

先创建一个测试表

CREATE TABLE IF NOT EXISTS userAccount(
id TINYINT UNSIGNED AUTO_INCREMENT KEY,
username VARCHAR(20) NOT NULL UNIQUE,
money DECIMAL(10,2)
)ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT userAccount(username,money) VALUES('imooc',10000),('king',5000);


<?php
//PDO事务处理
//事务处理的表,必须为INNODB
header('content-type:text/html;charset=utf-8');
try{
$dsn='mysql:host=localhost;dbname=test';
$username='root';
$passwd='root';
//PDO::ATTR_AUTOCOMMIT (integer)如果此值为 FALSE ,PDO 将试图禁用自动提交以便数据库连接开始一个事务。
$options=array(PDO::ATTR_AUTOCOMMIT,0);//关闭自动提交事物
$pdo=new PDO($dsn, $username, $passwd, $options);
var_dump($pdo->inTransaction());//检查是否在一个事务内
//开启事务
$pdo->beginTransaction();//启动一个事务
var_dump($pdo->inTransaction());
//$sql='UPDATE userAccount SET money=money-2000 WHERE username="imooc"';
$sql='UPDATE userAccount SET money=money-2000 WHERE username="imooc"';

$res1=$pdo->exec($sql);
if($res1==0){
throw new PDOException('imooc 转账失败');
}
$res2=$pdo->exec('UPDATE userAccount SET money=money+2000 WHERE username="king1"');
if($res2==0){
throw new PDOException('king 接收失败');
}
//提交事务
$pdo->commit();
}catch(PDOException $e){
//回滚事务
$pdo->rollBack();
echo $e->getMessage();
}


用PDO封装数据库操作类

PDO效率剖析

pdo的效率要低于mysql

PDO连接mysql效率和mysql连接对比

<?php
//PDO效率剖析
//与mysql对比
//结论是
//PDO比mysql连接数据库慢
//PDO插入数据比mysql要更费时
header('content-type:text/html;charset=utf-8');
//1.通过PDO连接数据库
$pStartTime=microtime(true);
for($i=1;$i<=100;$i++){
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
}
$pEndTime=microtime(true);
$res1=$pEndTime-$pStartTime;//时间差

//2.通过MySQL连接数据库
$mStartTime=microtime(true);
for($i=1;$i<=100;$i++){
mysql_connect('localhost','root','root');
mysql_select_db('test');
}
$mEndTime=microtime(true);
$res2=$mEndTime-$mStartTime;
echo $res1,'<br/>',$res2;
echo '<hr/>';
if($res1>$res2){
echo 'MySQL连接数据库效率是PDO的'.round($res1/$res2).'倍';
}else{
echo 'PDO连接数据库效率是MySQL的'.round($res2/$res1).'倍';
}


通过PDO和mysql插入数据对比

<?php
header('content-type:text/html;charset=utf-8');
//1.通过PDO连接数据库
$pStartTime=microtime(true);
$pdo=new PDO('mysql:host=localhost;dbname=test','root','root');
$sql='INSERT test2 VALUES(:id)';
$stmt=$pdo->prepare($sql);
for($i=1;$i<=500;$i++){
$id=1;
$stmt->bindParam(':id', $id,PDO::PARAM_INT);
$stmt->execute();
}
$pEndTime=microtime(true);
$res1=$pEndTime-$pStartTime;
unset($pdo);//$pdo=null;//关闭连接
//2.通过MySQL连接数据库
$mStartTime=microtime(true);
mysql_connect('localhost','root','root');
mysql_select_db('test');
for($i=1;$i<=500;$i++){
$sql='INSERT test2 VALUES(2)';
mysql_query($sql);
}
mysql_close();
$mEndTime=microtime(true);
$res2=$mEndTime-$mStartTime;
echo $res1,'<br/>',$res2;
echo '<hr/>';
if($res1>$res2){
echo 'PDO插入500条记录的费时是MySQL的'.round($res1/$res2).'倍';
}else{
echo 'MySQL插入500条记录的费时是PDO的'.round($res2/$res1).'倍';
}


封装PDO数据库操作类

数据库配置文件config.php

<?php
define("DB_HOST",'localhost');
define("DB_USER",'root');
define('DB_PWD','root');
define('DB_NAME','test');
define('DB_PORT','3306');
define('DB_TYPE','mysql');
define('DB_CHARSET','utf8');


封装的类PdoMySQL.class.php

<?php
header('content-type:text/html;charset=utf-8');
class PdoMySQL{
public static $config=array();//设置连接参数,配置信息
public static $link=null;//保存连接标识符
public static $pconnect=false;//是否开启长连接
public static $dbVersion=null;//保存数据库版本
public static $connected=false;//是否连接成功
public static $PDOStatement=null;//保存PDOStatement对象
public static $queryStr=null;//保存最后执行的操作
public static $error=null;//报错错误信息
public static $lastInsertId=null;//保存上一步插入操作产生AUTO_INCREMENT
public static $numRows=0;//上一步操作产生受影响的记录的条数
/**
* 连接PDO
* @param string $dbConfig
* @return boolean
*/
public function __construct($dbConfig=''){
if(!class_exists("PDO")){
self::throw_exception('不支持PDO,请先开启');
}
if(!is_array($dbConfig)){
$dbConfig=array(
'hostname'=>DB_HOST,
'username'=>DB_USER,
'password'=>DB_PWD,
'database'=>DB_NAME,
'hostport'=>DB_PORT,
'dbms'=>DB_TYPE,
'dsn'=>DB_TYPE.":host=".DB_HOST.";dbname=".DB_NAME
);
}
if(empty($dbConfig['hostname']))self::throw_exception('没有定义数据库配置,请先定义');
self::$config=$dbConfig;
if(empty(self::$config['params']))self::$config['params']=array();
if(!isset(self::$link)){
$configs=self::$config;
if(self::$pconnect){
//开启长连接,添加到配置数组中
$configs['params'][constant("PDO::ATTR_PERSISTENT")]=true;
}
try{
self::$link=new PDO($configs['dsn'],$configs['username'],$configs['password'],$configs['params']);
}catch(PDOException $e){
self::throw_exception($e->getMessage());
}
if(!self::$link){
self::throw_exception('PDO连接错误');
return false;
}
self::$link->exec('SET NAMES '.DB_CHARSET);
self::$dbVersion=self::$link->getAttribute(constant("PDO::ATTR_SERVER_VERSION"));
self::$connected=true;
unset($configs);
}
}

/**
* 得到所有记录
* @param string $sql
* @return unknown
*/
public static function getAll($sql=null){
if($sql!=null){
self::query($sql);
}
$result=self::$PDOStatement->fetchAll(constant("PDO::FETCH_ASSOC"));
return $result;
}
/**
* 得到结果集中的一条记录
* @param string $sql
* @return mixed
*/
public static function getRow($sql=null){
if($sql!=null){
self::query($sql);
}
$result=self::$PDOStatement->fetch(constant("PDO::FETCH_ASSOC"));
return $result;
}
/**
* 根据主键查找记录
* @param string $tabName
* @param int $priId
* @param string $fields
* @return mixed
*/
public static function findById($tabName,$priId,$fields='*'){
$sql='SELECT %s FROM %s WHERE id=%d';
return self::getRow(sprintf($sql,self::parseFields($fields),$tabName,$priId));
}

/**
* 执行普通查询
* @param unknown $tables
* @param string $where
* @param string $fields
* @param string $group
* @param string $having
* @param string $order
* @param string $limit
* @return Ambigous <unknown, unknown, multitype:>
*/
public static function find($tables,$where=null,$fields='*',$group=null,$having=null,$order=null,$limit=null){
$sql='SELECT '.self::parseFields($fields).' FROM '.$tables
.self::parseWhere($where)
.self::parseGroup($group)
.self::parseHaving($having)
.self::parseOrder($order)
.self::parseLimit($limit);
$dataAll=self::getAll($sql);
return count($dataAll)==1?$dataAll[0]:$dataAll;
}
/*
array(
'username'=>'imooc',
'password'=>'imooc',
'email'=>'imooc@imooc.com',
'token'=>'123abc',
'token_exptime'=>'123123',
'regtime'=>'123456'
)
INSERT user(username,password,email,token,token_exptime,regtime)
VALUES('aa','aa','aa@qq.com','bb','123123','123456')
*/
/**
* 添加记录的操作
* @param array $data
* @param string $table
* @return Ambigous <boolean, unknown, number>
*/
public static function add($data,$table){
$keys=array_keys($data);
array_walk($keys,array('PdoMySQL','addSpecialChar'));
$fieldsStr=join(',',$keys);
$values="'".join("','",array_values($data))."'";
$sql="INSERT {$table}({$fieldsStr}) VALUES({$values})";
//echo $sql;
return self::execute($sql);
}
/*
array(
'username'=>'imooc111',
'password'=>'imooc222',
'email'=>'imooc333@imooc.com',
'token'=>'4444',
'token_exptime'=>'1234444',
'regtime'=>'12345678'
)
UPDATE user SET username='imooc111',password='imooc222'.... WHERE id<=38 ORDER BY username limit 0,1
*/
/**
* 更新记录
* @param array $data
* @param string $table
* @param string $where
* @param string $order
* @param string $limit
* @return Ambigous <boolean, unknown, number>
*/
public static function update($data,$table,$where=null,$order=null,$limit=0){
foreach($data as $key=>$val){
$sets.=$key."='".$val."',";
}
//echo $sets;
$sets=rtrim($sets,',');
$sql="UPDATE {$table} SET {$sets} ".self::parseWhere($where).self::parseOrder($order).self::parseLimit($limit);
return self::execute($sql);
}
/**
* 删除记录的操作
* @param string $table
* @param string $where
* @param string $order
* @param number $limit
* @return Ambigous <boolean, unknown, number>
*/
public static function delete($table,$where=null,$order=null,$limit=0){
$sql="DELETE FROM {$table} ".self::parseWhere($where).self::parseOrder($order).self::parseLimit($limit);
return self::execute($sql);
}
/**
* 得到最后执行的SQL语句
* @return boolean|Ambigous <string, string>
*/
public static function getLastSql(){
$link=self::$link;
if(!$link)return false;
return self::$queryStr;
}
/**
* 得到上一步插入操作产生AUTO_INCREMENT
* @return boolean|string
*/
public static function getLastInsertId(){
$link=self::$link;
if(!$link)return false;
return self::$lastInsertId;
}
/**
* 得到数据库的版本
* @return boolean|mixed
*/
public static function getDbVerion(){
$link=self::$link;
if(!$link)return false;
return self::$dbVersion;
}
/**
* 得到数据库中数据表
* @return multitype:mixed
*/
public static function showTables(){
$tables=array();
if(self::query("SHOW TABLES")){
$result=self::getAll();
foreach($result as $key=>$val){
$tables[$key]=current($val);
}
}
return $tables;
}
/**
* 解析Where条件
* @param unknown $where
* @return string
*/
public static function parseWhere($where){
$whereStr='';
if(is_string($where)&&!empty($where)){
$whereStr=$where;
}
return empty($whereStr)?'':' WHERE '.$whereStr;
}
/**
* 解析group by
* @param unknown $group
* @return string
*/
public static function parseGroup($group){
$groupStr='';
if(is_array($group)){
$groupStr.=' GROUP BY '.implode(',',$group);
}elseif(is_string($group)&&!empty($group)){
$groupStr.=' GROUP BY '.$group;
}
return empty($groupStr)?'':$groupStr;
}
/**
* 对分组结果通过Having子句进行二次删选
* @param unknown $having
* @return string
*/
public static function parseHaving($having){
$havingStr='';
if(is_string($having)&&!empty($having)){
$havingStr.=' HAVING '.$having;
}
return $havingStr;
}
/**
* 解析Order by
* @param unknown $order
* @return string
*/
public static function parseOrder($order){
$orderStr='';
if(is_array($order)){
$orderStr.=' ORDER BY '.join(',',$order);
}elseif(is_string($order)&&!empty($order)){
$orderStr.=' ORDER BY '.$order;
}
return $orderStr;
}
/**
* 解析限制显示条数limit
* limit 3
* limit 0,3
* @param unknown $limit
* @return unknown
*/
public static function parseLimit($limit){
$limitStr='';
if(is_array($limit)){
if(count($limit)>1){
$limitStr.=' LIMIT '.$limit[0].','.$limit[1];
}else{
$limitStr.=' LIMIT '.$limit[0];
}
}elseif(is_string($limit)&&!empty($limit)){
$limitStr.=' LIMIT '.$limit;
}
return $limitStr;
}
/**
* 解析字段
* @param unknown $fields
* @return string
*/
public static function parseFields($fields){
if(is_array($fields)){
array_walk($fields,array('PdoMySQL','addSpecialChar'));
$fieldsStr=implode(',',$fields);
}elseif(is_string($fields)&&!empty($fields)){
if(strpos($fields,'`')===false){
$fields=explode(',',$fields);
array_walk($fields,array('PdoMySQL','addSpecialChar'));
$fieldsStr=implode(',',$fields);
}else{
$fieldsStr=$fields;
}
}else{
$fieldsStr='*';
}
return $fieldsStr;
}
/**
* 通过反引号引用字段,
* @param unknown $value
* @return string
*/
public static function addSpecialChar(&$value){
if($value==='*'||strpos($value,'.')!==false||strpos($value,'`')!==false){
//不用做处理
}elseif(strpos($value,'`')===false){
$value='`'.trim($value).'`';
}
return $value;
}
/**
* 执行增删改操作,返回受影响的记录的条数
* @param string $sql
* @return boolean|unknown
*/
public static function execute($sql=null){
$link=self::$link;
if(!$link) return false;
self::$queryStr=$sql;
if(!empty(self::$PDOStatement))self::free();
$result=$link->exec(self::$queryStr);
self::haveErrorThrowException();
if($result){
self::$lastInsertId=$link->lastInsertId();
self::$numRows=$result;
return self::$numRows;
}else{
return false;
}
}
/**
*释放结果集
*/
public static function free(){
self::$PDOStatement=null;
}
public static function query($sql=''){
$link=self::$link;
if(!$link) return false;
//判断之前是否有结果集,如果有的话,释放结果集
if(!empty(self::$PDOStatement))self::free();
self::$queryStr=$sql;
self::$PDOStatement=$link->prepare(self::$queryStr);
$res=self::$PDOStatement->execute();
self::haveErrorThrowException();
return $res;
}
public static function haveErrorThrowException(){
$obj=empty(self::$PDOStatement)?self::$link: self::$PDOStatement;
$arrError=$obj->errorInfo();
//print_r($arrError);
if($arrError[0]!='00000'){
self::$error='SQLSTATE: '.$arrError[0].' <br/>SQL Error: '.$arrError[2].'<br/>Error SQL:'.self::$queryStr;
self::throw_exception(self::$error);
return false;
}
if(self::$queryStr==''){
self::throw_exception('没有执行SQL语句');
return false;
}
}
/**
* 自定义错误处理
* @param unknown $errMsg
*/
public static function throw_exception($errMsg){
echo '<div style="width:80%;background-color:#ABCDEF;color:black;font-size:20px;padding:20px 0px;">
'.$errMsg.'
</div>';
}
/**
* 销毁连接对象,关闭数据库
*/
public static function close(){
self::$link=null;
}

}
require_once 'config.php';
$PdoMySQL=new PdoMySQL;
//var_dump($PdoMySQL);
// $sql='SELECT * FROM user1';
// print_r($PdoMySQL->getAll($sql));
// $sql='SELECT * FROM user WHERE id=36';
// print_r($PdoMySQL->getRow($sql));
// $sql='INSERT user(username,password,email,token,token_exptime,regtime)';
// $sql.=" VALUES('imooc1113','imooc1113','imooc1113@imooc.com','abcdefgh','1392348346','12313346')";
// //echo $sql;
// var_dump($PdoMySQL->execute($sql));
// echo '<hr/>';
// echo $PdoMySQL::$lastInsertId;
// $sql='DELETE FROM user WHERE id>=37';
// var_dump($PdoMySQL->execute($sql));
// $sql='UPDATE user SET username="king1234" WHERE id=36';
// var_dump($PdoMySQL->execute($sql));
// $tabName='user';
// $priId='36';
// //$fields='username,email';
// $fields=array('username','email','regtime');
// $fields='*';
// print_r($PdoMySQL->findById($tabName,$priId,$fields));
//print_r($PdoMySQL->findById($tabName, $priId));
$tables='user';
//print_r($PdoMySQL->find($tables));
//print_r($PdoMySQL->find($tables,'id>=30'));
// print_r($PdoMySQL->find($tables,'id>=30','username,email'));
//print_r($PdoMySQL->find($tables,'id<=10','*','status'));
//print_r($PdoMySQL->find($tables,'id<=10','*','status','count(*)>=6'));
//print_r($PdoMySQL->find($tables,'id>5','*',null,null,'username desc,id desc'));
//print_r($PdoMySQL->find($tables,null,'*',null,null,null,array(3,5)));
// $data= array(
//   'username'=>'imooc',
//   'password'=>'imooc',
//   'email'=>'imooc@imooc.com',
//   'token'=>'123abc',
//   'token_exptime'=>'123123',
//   'regtime'=>'123456'
//   );
// var_dump($PdoMySQL->add($data,$tables));
// $data=array(
//   'username'=>'imooc111',
//   'password'=>'imooc222',
//   'email'=>'imooc333@imooc.com',
//   'token'=>'4444',
//   'token_exptime'=>'1234444',
//   'regtime'=>'12345678'
// );
//var_dump($PdoMySQL->update($data,$tables,'id<=38',' id DESC','2'));

//var_dump($PdoMySQL->delete($tables,'id>35'));
//var_dump($PdoMySQL->delete($tables,'id>3','id DESC','5'));
//print_r($PdoMySQL->showTables());
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: