数据库抽象层 PDO

数据库抽象层 PDO

链接与链接管理

如果有任何连接错误,将抛出一个 PDOException 异常对象。如果想处理错误状态,可以捕获异常,或者选择留给通过 set_exception_handler() 设置的应用程序全局异常处理程序。

<?php
try {
    $dbh = new PDO('mysql:host=localhost;dbname=test',$user,$pass);
    foreach($dbh->query('select * from FOO') as $row){
        print_r($row);
    }
} catch(PDOException $e){
    print "ERROR!:".$e->getMessage()."<br/>";
    die();
}
?>

事务与自动提交

事务支持四大特性(ACID):原子性(Atomicity)、一致性(Consistency)隔离性(Isolation)以及持久性(Durability)

如果需要一个事务,则必须用 PDO::beginTransaction() 方法来启动。如果底层驱动不支持事务,则抛出一个 PDOException 异常(不管错误处理设置是怎样的,这都是一个严重的错误状态)。一旦开始了事务,可用 PDO::commit()PDO::rollBack()来完成,这取决于事务中的代码是否运行成功。

当脚本结束或连接即将被关闭时,如果尚有一个未完成的事务,那么 PDO 将自动回滚该事务。这种安全措施有助于在脚本意外终止时避免出现不一致的情况——如果没有显式地提交事务,那么假设是某个地方出错了,所以执行回滚来保证数据安全。

Example #1 在事务中执行批处理

在下面例子中,假设为新员工创建一组条目,分配一个为23的ID。除了登记此人的基本数据之外,还需要记录他的工资。两个更新分别完成起来很简单,但通过封闭在 PDO::beginTransaction()PDO::commit() 调用中,可以保证在更改完成之前,其他人无法看到这些更改。如果发生了错误,catch 块回滚自事务启动以来发生的所有更改,并输出一条错误信息。

<?php
try{
    $dbh = new PDO('odbc:SAMPLE','db2inst1','ibmdb2',array(PDO::ATTR_PERSISTENT =>true));
    echo "Connected\n";
}catch(Exception $e){
    die("Unable to connect:".$e->getMessage());
}

try{
    $dbh -> setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    $bdh -> beginTransaction();
    $bdh -> exec("insert into staff (id,first,last) values(23,'JOE','Bloggs')");
    $bdh -> exec("insert into salarychange (id,amount,changedate) values (23,5000,Now())");
    $dbh -> commit();
}catch(Exception $e) {
    $dbh -> rollBack();
    echo "Failed:".$e -> getMeseeage();
}
?>

预处理语句与存储过程

Example #1 用预处理语句进行重复插入

<?php
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);

// 插入一行
$name = 'one';
$value = 1;
$stmt->execute();

//  用不同的值插入另一行
$name = 'two';
$value = 2;
$stmt->execute();
?>

Example #2 用预处理语句进行重复插入

下面例子通过用 name 和 value 取代 ? 占位符的位置来执行一条插入查询。

<?php
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);

// 插入一行
$name = 'one';
$value = 1;
$stmt->execute();

// 用不同的值插入另一行
$name = 'two';
$value = 2;
$stmt->execute();
?>

Example #3 使用预处理语句获取数据

下面例子获取数据基于键值已提供的形式。用户的输入被自动用引号括起来,因此不会有 SQL 注入攻击的危险。

<?php
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
if ($stmt->execute(array($_GET['name']))) {
  while ($row = $stmt->fetch()) {
    print_r($row);
  }
}
?>

Example #6 占位符的无效使用

<?php
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'");
$stmt->execute(array($_GET['name']));

// 占位符必须被用在整个值的位置
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE ?");
$stmt->execute(array("%$_GET[name]%"));
?>

错误与错误处理

PDO 提供了三种不同的错误处理模式,以满足不同风格的应用开发:

  • PDO::ERRMODE_SILENT
  • PDO::ERRMODE_WARNING
  • PDO::ERRMODE_EXCEPTION

Example #1 创建 PDO 实例并设置错误模式

<?php
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';

try {
    $dbh = new PDO($dsn, $user, $password);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}
?>

Note: 不管当前是否设置了 PDO::ATTR_ERRMODE ,如果连接失败,PDO::__construct() 将总是抛出一个 PDOException 异常。未捕获异常是致命的。 Example #2 创建 PDO 实例并在构造函数中设置错误模式

<?php
$dsn = 'mysql:dbname=test;host=127.0.0.1';
$user = 'googleguy';
$password = 'googleguy';

/*
    使用 try/catch 围绕构造函数仍然有效,即使设置了 ERRMODE 为 WARNING,
    因为如果连接失败,PDO::__construct 将总是抛出一个  PDOException 异常。
*/
try {
    $dbh = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
    exit;
}

// 这里将导致 PDO 抛出一个 E_WARNING 级别的错误,而不是 一个异常 (当数据表不存在时)
$dbh->query("SELECT wrongcolumn FROM wrongtable");
?>

以上例程会输出:

Warning: PDO::query(): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.wrongtable' doesn't exist in /tmp/pdo_test.php on line 18

转载于:https://my.oschina.net/liangwt/blog/739025

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值