码迷,mamicode.com
首页 > 数据库 > 详细

PDO数据库抽象层

时间:2016-05-18 19:58:32      阅读:325      评论:0      收藏:0      [点我收藏+]

标签:

什么是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连接数据库

  1. 通过参数的形式连接数据库(建议用第一种比较好用)
  2. 通过uri的方式连接数据库
  3. 通过配置文件连接数据库

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

<?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());




PDO数据库抽象层

标签:

原文地址:http://blog.csdn.net/everything1209/article/details/51392093

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!