关于PDO--数据库抽象层

1.什么是PDO?

PDO(PHP Data Object),数据库访问抽象层,统一各种数据库的访问接口。
PDO的特性:

  1. 编码一致性
  2. 灵活性
  3. 高性能
  4. 面向对象特性

2.PDO的安装与配置

  1. 配置PHP配置文件,开启相应扩展
    extension=php_pdo_mysql.dll
  2. 通过查看phpinfo可以看到PDO扩展的详细信息

这里写图片描述

3.PDO连接到数据库

  1. 通过参数形式连接数据库
  2. 通过URI形式连接数据库
  3. 通过配置文件形式连接数据库

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

<?php
    try {
        $dsn = "mysql:host=localhost;dbname=egovacms_db2";
        $username = "root";
        $password = "";
        $pdo = new PDO($dsn, $username, $password);
    }catch(PDOException $e) {
        echo $e->getMessage();
    }
?>

3.2通过uri的形式连接数据库
1.pdo_connect.php

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

2.dsn.txt

mysql:host=localhost;dbname=egovacms_db2

3.3使用配置文件连接数据库
1.打开php.ini配置文件,在任意位置添加,我在[PHP]下面添加了这样一行代码

pdo.dsn.zjp = "mysql:host=localhost;dbname=egovacms_db2";

2.重启服务器
3.测试连接

<?php
    try {
        $dsn = 'zjp';
        $username = 'root';
        $password = '';
        $pdo = new PDO($dsn, $username, $password);
        var_dump($pdo);
    }catch(PDOException $e) {
        echo $e->getMessage();
    } 
?>

4.PDO方法

4.1exec()执行建表语句

<?php
try {
    $dsn = 'mysql:host=localhost;dbname=testpdo';
    $username = 'root';
    $password = '';
    $pdo = new PDO($dsn, $username, $password);
    $sql = <<<EOF
        CREATE TABLE IF NOT EXISTS user(
            id INT UNSIGNED AUTO_INCREMENT KEY,
            uesrname VARCHAR(20) NOT NULL UNIQUE,
            password VARCHAR(32) NOT NULL,
            email VARCHAR(32) NOT NULL
        );
EOF;
    $res = $pdo->exec($sql);
    var_dump($res);
}catch(PDOException $e) {
    echo $e->getMessage();
} 
?>

执行这段代码后会发现数据库中创建了user表,屏幕输入int(0);
4.2exec()执行插入操作

$sql = 'INSERT user(username, password, email) VALUES("zjp", "'.md5('zjp').'", "zjp@qq.com")';
$res = $pdo->exec($sql);
var_dump($res);
echo "最后插入的ID号:".$pdo->lastInsertId();

会发现user表中多出了一条数据,屏幕输入int(1)
PDO还提供了查看最后插入那条数据的ID号。lastInsertId();
同样的update和delete也可以这样来执行,这里就不赘述了。
4.3errorCode()和errorInfo()方法

<?php
    //user12表示不存在的
    $sql = "delete * from user12 where id = 1";
    $res = $pdo->exec($sql);
    if($res==false) {
        //输出错误信息
        echo 'SQLSTATE值:'.$pdo->errorCode();
        echo '<br/>';
        //errorInfo()返回错误信息的数组
        //0=>SQLSTATE,1=>CODE,2=>INFO
        print_r($pdo->errorInfo());
    }
?>

4.4query()方法查询数据
因为exec()是不能执行查询操作的,所以出现了query()方法。

//查询数据库中的数据,执行成功后返回一个pdostatement对象
$sql = 'SELECT * FROM user';
$stmt = $pdo->query($sql);
//取出数据使用foreach()遍历
foreach($stmt as $row) {
    echo '编号:'.$row['id'].'<br/>';
    echo '用户名:'.$row['username'].'<br/>';
    echo '邮箱:'.$row['email'].'<br/>';
    echo '<hr>';
}
//这样就输出了查询到的数据了

我们可以尝试,使用query()同样可以执行insert,update等语句,但一般情况下我们还是使用query()来进行查询操作,使用exec()来进行增删改操作。
4.5prepare()预处理和execute()执行

//需要执行的SQL语句
$sql = 'SELETE * FROM user';
//预处理SQL语句
$stmt = $pdo->prepare($sql);
//执行SQL语句
$res = $stmt->execute();
//如果查询到结果就遍历出来
if($res) {
    whild($row = $stmt->fetch()) {
        print_r($row);
        echo '<br/>';
    }
    //也可以使用fetchAll()方法来获取全部数据
    print_r($stmt->fetchAll());
}

我获得的数据是关联加索引形式的数组:
这里写图片描述
一般情况下在项目中,我们使用的是关联数组,那么如何只获取关联数组呢。
PDO为我们提供了方法。返回数据的形式有很多哦。

$stmt->fetch(PDO::FETCH_ASSOC)

同样的在fetchAll()方法中也可以使用。
4.6getAttribute()和setAttribute()

echo '自动提交:'.$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);

可以看到输出结果:自动提交:1。默认是开启自动提交的
同样可以使用setAttribute()来设置数据库的属性

$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);
echo '自动提交:'.$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);

这是就会输出:自动提交:0。
4.7使用prepare()和execute()防止SQL注入
login.html

<form action='doLogin.php' method='post'>
<input type='text' name='username' value='' />
<input type='password' name='password' value='' />
<input type='submit' value='Login' />
</form>

doLogin.php

<?php 
header('Content-Type:text/html;charset=utf-8');
$username = $_POST['username'];
$password = $_POST['password'];
try {
    $pdo = new PDO('mysql:host=localhost;dbname=testpdo', 'root', '');
    //第一种占位符
    $sql = "SELECT * FROM user WHERE username=:username AND password=:password";
    //第二种占位符
    $sql = "SELECT * FROM user WHERE username=? AND password=?";
    $stmt = $pdo->prepare($sql);
    //第一种传参
    $stmt = execute(array(":username"=>$username, "password"=>$password));
    //第二种传参
    $stmt = execute(array($username, $password));
    echo $stmt->rowCount();
}catcch(PDOException $e) {
    echo $e->getMessage();
}
?>

4.8bindParam()方法绑定参数

//第一种绑定参数的方法
$sql = "SELECT * FROM user WHERE username=:username AND password=:password";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password);
$username = 'zjp';
$password = 'zjp';
$stmt->execute();
$username = 'wxd';
$password = 'wxd';
$stmt->execute();
//第二种绑定参数的方法
$sql = "SELECT * FROM user WHERE username=? AND password=?";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(0, $username);
$stmt->bindParam(1, $password);
$username = 'zjp';
$password = 'zjp';
$stmt->execute();
$username = 'wxd';
$username = 'wxd';
$stmt->execute();

4.9bindValue()绑定值
与bindParam()的区别在于,bindValue()是可以绑定一个特定值得,而bindParam()只能绑定地址,也就是变量。

$sql = "INSERT user(username, password, email) VALUES(?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(0, $uesrname);
$stmt->bindValue(1, $password);
$stmt->bindValue(3, 'zjp@qq.com');
$username = 'zjp';
$password = 'zjp';
$stmt->execute();

这样添加进去的数据,email的值就都为zjp@qq.com了。
4.10bindColumn()方法
简单的举一个例子就能看懂了:

$sql = "SELECT username,password,email FROM user";
$stmt = $pdo->prepare($sql);
$stmt->execute();
//获取结果集中的列数
echo '结果集中的列数一共有:'.$stmt->columnCount().'<hr/>';
$stmt->bindColumn(1, $username); //绑定第一列到$username下
$stmt->bindColumn(2, $password); //绑定第二列到$password下
$stmt->bindColumn(3, $email);    //绑定第三列到$email下
//取出数据,这里要使用fetch中一个为bindColumn()准备的参数
while($stmt->fetch(PDO::FETCH_BOUND)) {
    echo '用户名:'.$username.'-密码:'.$password.'-邮箱:'.$email.'<br/>';
}

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

$stmt->execute();
$stmt->debugDumpParams();

5.PDO错误处理模式

<?php 
/*
 * PDO::ERRMODE_SLIENT:默认模式,静默模式
 */
try {
    $pdo = new PDO('mysql:host=localhost;dbname=testpdo', 'root', '');
    $sql = 'SELECT * FROM user12'; //user12不存在
    $pdo->query($sql);
    //这时候并不会输出任何信息,只有使用$pdo->errorCode()方法和$pdo->errorInfo()方法来获取错误消息
}catch(PDOException $e) {
    echo $e->getMessage();
}
?>


<?php 
/*
 * PDO::ERRMODE_WARNING:警告模式
 */
try {
    $pdo = new PDO('mysql:host=localhost;dbname=testpdo', 'root', '');
    //设置错误模式
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
    $sql = 'SELECT * FROM user12'; //user12不存在
    $pdo->query($sql);
    //这时候会出现warning的警告消息,然后使用$pdo->errorCode()方法和$pdo->errorInfo()方法来可以获取错误消息
}catch(PDOException $e) {
    echo $e->getMessage();
}
?>


<?php 
/*
 * PDO::ERRMODE_EXCEPTION:异常模式
 */
try {
    $pdo = new PDO('mysql:host=localhost;dbname=testpdo', 'root', '');
    //设置错误模式
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $sql = 'SELECT * FROM user12'; //user12不存在
    $pdo->query($sql);
    //这时候会出现具体的错误信息,包括错误代码,错误消息,就不需要使用$pdo->errorCode()方法和$pdo->errorInfo()方法来可以获取错误消息,这也是我们最常使用的错误模式
}catch(PDOException $e) {
    echo $e->getMessage();
}
?>

6.PDO事务处理

例子:
记住要使用INNODB表引擎

<?php 
header('Content-Type:text/html;charset=utf-8');
try {
    $dsn = 'mysql:host=localhost;dbname=testpdo';
    $username = 'root';
    $password = '';
    $options = array(PDO::ATTR_AUTOCOMMIT, 0);//取消自动提交
    $pdo = new PDO($dsn, $username, $password, $options);
    //开启事务
    $pdo->beginTransaction();
    $sql1 = 'UPDATE account SET money=money-200 WHERE username="zjp"';
    $res1 = $pdo->exec($sql1);
    if($res1==0) {
        throw new PDOException('zjp转账失败');
    }
    $sql2 = 'UPDATE account SET money=money+200 WHERE username="wxd"';
    $res2 = $pdo->exec($sql2);
    if($res2==0) {
        throw new PDOException('wxd接收失败');
    }
    //提交事务
    $pdo->commit();
}catch(PDOException $e) {
    //回滚事务
    $pdo->rollBack(); 
    echo $e->getMessage();
}
?>

这里多提一点,也是前几天面试时候面试官考察我的地方。
在这个事务中,如果我的第一条SQL语句是对的,第二条SQL语句是错误的,那么当我执行第一条SQL语句后,查询一下值得时候,第一条SQL语句中的zjp的money变没变,这里大家可以自己测试一下,其实是变了的。当第二条SQL错误的时候,才会回滚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值