码迷,mamicode.com
首页 > 其他好文 > 详细

PDO

时间:2015-05-20 11:33:41      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:

连接数据库

创建一个 PDO 对象,参数包括 DSNusernamepassword 和一个驱动选项的数组(可选)。
DSN 是一个告诉 PDO 该使用哪一种数据库驱动和一些连接信息的字符串。

$db = new PDO(‘mysql:host=localhost;dbname=testdb;charset=utf8‘, ‘username‘, ‘password‘);

确保 DSN 中设置了字符编码信息,否则将可能返回字符编码设置错误的信息。
可以在第四个参数数组里填写一些驱动选项,建议填写 PDO异常模式,并关闭 预处理模拟(默认打开,仅对于旧版本 MySQL 有用)。

$db = new PDO(
    ‘mysql:host=localhost;dbname=testdb;charset=utf8‘,
    ‘username‘,
    ‘password‘,
    array(
        PDO::ATTR_EMULATE_PREPARES => false,
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    )
);

也可以在创建 PDO 对象后再通过 setAttribute 方法设置相应选项。

$db = new PDO(‘mysql:host=localhost;dbname=testdb;charset=utf8‘, ‘username‘, ‘password‘);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

错误处理

PDO 有三种错误处理模式:

  1. PDO::ERRMODE_SILENTmysql_* 函数类似,检查代码并查看 $db->errorInfo() 获取详细信息
  2. PDO::ERRMODE_WARNING 抛出 PHP 警告
  3. PDO::ERRMODE_EXCEPTION 抛出 PDOException 异常。建议使用这种模式,可以捕获并抛出具体异常信息
try {
    $db->query(‘hi‘); // 非法查询
} catch(PDOException $ex) {
    echo ‘An Error occured!‘;
    some_logging_function($ex->getMessage());
}

不必立即执行并捕获异常,可以在任何合适的时候随时捕获:

function getData($db) {
   $stmt = $db->query("SELECT * FROM table");
   return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

//then much later
try {
   getData($db);
} catch(PDOException $ex) {
   //handle me.
}

简单的查询语句(SELECT)

获取查询结果集

SELECT 操作使用 query() 方法,返回一个 PDOStatement 对象。

$stmt = $db->query(‘SELECT * FROM table‘);
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    echo $row[‘field1‘] . ‘ ‘ . $row[‘field2‘]; //etc...
}

// 或者

$stmt = $db->query(‘SELECT * FROM table‘);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
//use $results

fetch()fetchAll() 中的参数:

  • PDO::FETCH_ASSOC,以关联数组的形式返回键值
  • PDO::FETCH_NUM,以索引数组的形式返回键值
  • PDO::FETCH_BOTH,返回前两者的集合
  • PDO::FETCH_OBJ,以对象的形式返回键值

获取查询结果集的行数

$stmt = $db->query(‘SELECT * FROM table‘);
$row_count = $stmt->rowCount();
echo $row_count . ‘ rows selected‘;

官方文档称 rowCount() 仅适用于返回 UPDATE、INSERT、DELETE 操作的 affected rows,而 SELECT 操作,仅对于 PDO_MYSQL 驱动适用,操作其他数据库时要注意。

获取最后插入 ID

$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES(‘John‘, ‘Doe‘)");
$insertId = $db->lastInsertId();

执行 INSERT、UPDATE、DELETE 操作

这 3 种操作统一使用 exec() 方法,返回 affected_rows。


$affected_rows = $db->exec("UPDATE table SET field=‘value‘"); echo $affected_rows . ‘ were affected‘;

运行带有查询参数的语句

绑定参数

对于不携带任何参数的查询语句,可以使用 query 方法处理 SELECT 操作,使用 exec 方法处理 INSERT、UPDATE、INSERT操作,而对于携带查询参数的语句,应该使用绑定参数的方法来安全地处理这些操作。

$stmt = $db->prepare("SELECT * FROM table WHERE id=? AND name=?");
$stmt->execute(array($id, $name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

prepare 方法将查询语句发送到服务器,以 ? 作为参数占位符进行编译,execute 方法将查询参数发送到服务器,运行之前编译好的查询语句。因为查询语句和查询参数是分开发送的,所以在参数里的 SQL 语句是不可能被执行的,所以不会发生 SQL 注入,这是一种比连接字符串构造 SQL 语句更加安全的解决方法。
当你使用 prepare 时,不要对 ? 占位符使用引号(SQL 语句原本是对参数使用引号的),因为参数类型是在 execute 方法里确定的。

bindValue 方法可以分别绑定每个参数来代替 execute 方法的数组方式,同时还分别设置每个参数的类型:

$stmt = $db->prepare("SELECT * FROM table WHERE id=? AND name=?");
$stmt->bindValue(1, $id, PDO::PARAM_INT);
$stmt->bindValue(2, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

命名占位符

如果有许多参数需要绑定,不要使用 ? 占位符,以防混淆出错,可以使用命名占位符。

$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(‘:name‘ => $name, ‘:id‘ => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

// 或者

$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->bindValue(‘:id‘, $id, PDO::PARAM_INT);
$stmt->bindValue(‘:name‘, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

INSERT、DELETE、UPDATE 预处理查询

INSERT、DELETE、UPDATE 预处理语句的使用和 SELECT 类似。

$stmt = $db->prepare("INSERT INTO table(field1,field2,field3,field4,field5) VALUES(:field1,:field2,:field3,:field4,:field5)");
$stmt->execute(array(‘:field1‘ => $field1, ‘:field2‘ => $field2, ‘:field3‘ => $field3, ‘:field4‘ => $field4, ‘:field5‘ => $field5));
$affected_rows = $stmt->rowCount();

$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(‘:id‘, $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();

$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();

在预处理中使用 SQL 函数

$name = ‘BOB‘;
$stmt = $db->prepare("INSERT INTO table(`time`, `name`) VALUES(NOW(), ?)");
$stmt->execute(array($name));

// 在SQL函数里绑定参数
$name = ‘BOB‘;
$password = ‘badpass‘;
$stmt = $db->prepare("INSERT INTO table(`hexvalue`, `password`) VALUES(HEX(?), PASSWORD(?))");
$stmt->execute(array($name, $password));

使用循环运行预处理语句

预处理语句可以一次设置多次调用。因为仅在第一次传入时编译,所以后来的多次调用效率提高了不少。
典型的应用就是 bindParambindParambindValue 的不同之处在于它不是绑定了参数的值,而是绑定参数变量本身。如果参数变量变化了,那么在 execute 处理的时候,查询也将相应变化。

$values = array(‘bob‘, ‘alice‘, ‘lisa‘, ‘john‘);
$name = ‘‘;
$stmt = $db->prepare("INSERT INTO table(`name`) VALUES(:name)");
$stmt->bindParam(‘:name‘, $name, PDO::PARAM_STR);
foreach($values as $name) {
   $stmt->execute();
}

事务

try {
    $db->beginTransaction();
    $db->exec("SOME QUERY");
    $stmt = $db->prepare("SOME OTHER QUERY?");
    $stmt->execute(array($value));
    $stmt = $db->prepare("YET ANOTHER QUERY??");
    $stmt->execute(array($value2, $value3));
    $db->commit();
} catch(PDOException $ex) {
    //Something went wrong rollback!
    $db->rollBack();
    echo $ex->getMessage();
}

调用 beginTransaction() 方法即自动关闭了自动提交。

PDO

标签:

原文地址:http://my.oschina.net/u/1991338/blog/417097

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