PDO驱动使用

PDO 使用

PDO扩展:

1、安装扩展 php_pdo.dll
2、安装驱动 php_pdo_mysql.dll

linux 编译时参数:--with-pdo=mysql=/usr/local/mysql

DSN表示:

data source name(数据源) 包括 主机、库名、驱动名

mysql:host=localhost;port=3307;dbname=testdb
mysql:unix_socket=/tmp/mysql.sock;dbname=testdb

PDO对象使用

1. 创建对象:

$dsn = "mysql:host=127.0.0.1;port=3306;dbname=test";
$opts = array(
    PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'",
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, 
    PDO::ATTR_AUTOCOMMIT => 0 #关闭自动提交, 
    PDO::ATTR_TIMEOUT => 3 #设置超时时间
);
$pdo = new PDO($dsn, 'root', '', $opts);
// setAttribute 可以设置属性
$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);
// 设置获取的方式 
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); 

异常处理常量:

  • PDO::ERRMODE_SILENT(0): 默认 不提示任何错误
    连接时无论如何都会提示,只有在执行后面的方法时才会起作用
  • PDO::ERRMODE_WARNING(1 : 警告
  • PDO::ERRMODE_EXCEPTION(2):异常(推荐使用)
    用try catch捕获,也可以手动抛出异常 new PDOException($message, $code, $previous)

2. 执行sql语句 -- exec() 、query()、 perpare()

  • query: 用来处理有结果集的,如select, 返回 PDOStatement 对象,失败返回false(当为 PDO::ERRMODE_SILENT,这也是默认的值)
  • exec: 用来处理有返回影响行数的(int),如 insert(插入的行数)、 delete(删除的行数) 、update(和原数值不等才算), 失败返回false (当为 PDO::ERRMODE_SILENT,这也是默认的值)
  • prepare: 执行所有sql,可以完全替代 query,exec的功能

exec用法:

//exec用法
try {
    $sql = "INSERT INTO example(id, name, age) VALUES(1, 'xiaohong', 19)";
    $rows = $pdo->exec($sql);  //影响的条数 2
    $pdo->lastInsertId(); //最后插入的id,有多条时返回的是第一条的id
} catch (Exception $e) {
    ee($pdo->errorInfo());
}

query用法:

#query方法同样也可以执行insert,delete 只是返回的结果集的格式
#同样 lastInsertId 照样也可以使用
$statement = "INSERT INTO example(id, name, age) VALUES(2, 'xiaogang', 19)";
$flag = $pdo->query($statement);
var_dump($flag);
var_dump($pdo->lastInsertId());
#query可以实现所有exec的功能
$statement = "INSERT INTO example(id, name, age) VALUES(3, 'xiaoming', 19)";
$statement = "SELECT * FROM example";
$statement = "DELETE  FROM example WHERE id = 1";
$statement = "UPDATE example set age=5 WHERE id = 1";

$stmt = $pdo->query($statement);
var_dump($stmt->rowCount());

总结:

  • 1、query和exec都可以执行所有的sql语句,只是返回值不同而已。
  • 2、query可以实现所有exec的功能。
  • 3、当把select语句应用到 exec 时,总是返回 0
    1. 注意:批量插入时,依次插入当遇到错误时后面的插入失败,但是前面的会插入成功。

预处理语句(prepare):

# pdo中有两种占位符号
# ? 参数             --- 索引数组, 按索引顺序使用
# 名子参数           ----关联数组, 按名称使用,和顺序无关 
//准备好了一条语句,并入到服务器端,也已经编译过来了,就差为它分配数据过来
//同样适用于更新操作
$stmt=$pdo->prepare("INSERT INTO example(`name`, `age`) VALUES(:name,:age)");

//绑定参数,引用方式传递
$stmt->bindParam(":name", $name);
$stmt->bindParam(":age", $age);

//所有SQL都可执行
// $stmt=$pdo->prepare("INSERT INTO example(`name`, `age`) VALUES(?, ?)"); 
//绑定参数,引用方式传递
// $stmt->bindParam(1, $name, PDO::PARAM_STR); #起始值为 1 
// $stmt->bindParam(2, $age, PDO::PARAM_INT);

#变量放到 bindParam 前后都可
$name  = "xiaoji";
$order = 30;

if($stmt->execute()){
    echo "执行成功";
    echo "最后插入的ID:".$pdo->lastInsertId();
}else{
    echo "执行失败!";
}

支持执行时绑定:

#无序方式
$stmt=$pdo->prepare("INSERT INTO example(`name`, `age`) VALUES(:name,:age)"); 
$stmt->execute(array(":name"=>"xiaohuang", ":age"=>"13");
$stmt->execute(array(":name"=>"xiaomi", ":age"=>"23");

#有序方式
//所有SQL都可执行
$stmt=$pdo->prepare("INSERT INTO example(`name`, `age`) VALUES(?,?)"); 
$stmt->execute(array("xiaohuang", "13"));
$stmt->execute(array("xiaomi", "23"));

获取结果:

//获取结果
$stmt = $pdo->prepare("SELECT * FROM example where `age` = :age");
$stmt->execute(array(':age'=>8));
//设置获取的方式
$stmt->setFetchMode(PDO::FETCH_ASSOC);

$data = array();

//方式1
//$data = $stmt->fetchAll();

//方式2
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    $data[] = $row;
}
var_dump($data);

#所有的条数,select insert delete update
$rowCount = $stmt->rowCount();
var_dump($rowCount);

事务:

/*
 *
 * 事务处理
 *   张三从李四那里买了一台 2000 元的电脑
 *     从张三帐号中扣出 2000元
 *     向李四账号中加入 2000元
 *     从商品表中减少一台电脑
 *     MyIsAM  InnoDB
 */

try{
    $pdo->beginTransaction();
    $price=500;
    $sql="update zhanghao set price=price-{$price} where id=1";
    $affected_rows=$pdo->exec($sql);

    if(!$affected_rows){
        throw new PDOException("张三转出失败");
    }
    $sql="update zhanghao set price=price+{$price} where id=3";
    $affected_rows=$pdo->exec($sql);

    #发现问题手动抛出异常
    if(!$affected_rows) {
        throw new PDOException("向李四转入失败"); 
    }
    echo "交易成功!";
    $pdo->commit();
}catch(PDOException $e){
    echo $e->getMessage();
    $pdo->rollback(); //只要捕获异常则回滚
}

//不管执行成功还是失败最后都要在关闭自动提交
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);

更好的获取条数:

# SQL_CALC_FOUND_ROWS 只要执行一次较耗时的复杂查询可以同时得到与不带limit同样的记录条数
$pdo->setAttribute(array(PDO::MYSQL_USE_BUFFERED_QUERY=>TRUE)); 
$rs  = $pdo->query('SELECT SQL_CALC_FOUND_ROWS * FROM table LIMIT 5,15'); 
$rs1 = $pdo->query('SELECT FOUND_ROWS()'); 
$rowCount = (int) $rs1->fetchColumn(); 
/*  使用一个数组的值执行一条含有 IN 子句的预处理语句 */
$params = array(1, 21, 63, 171);
/*  创建一个填充了和params相同数量占位符的字符串 */
$place_holders = implode(',', array_fill(0, count($params), '?'));
/*
    对于 $params 数组中的每个值,要预处理的语句包含足够的未命名占位符 。
    语句被执行时, $params 数组中的值被绑定到预处理语句中的占位符。
    这和使用 PDOStatement::bindParam() 不一样,因为它需要一个引用变量。
    PDOStatement::execute() 仅作为通过值绑定的替代。
*/
$sth = $pdo->prepare("SELECT id, name FROM contacts WHERE id IN ($place_holders)");
$sth->execute($params);



$data = ['a'=>'foo','b'=>'bar'];
$keys = array_keys($data);
$fields = '`'.implode('`, `',$keys).'`'; 
$placeholder = substr(str_repeat('?,',count($keys),0,-1));
$pdo->prepare("INSERT INTO `baz`($fields) VALUES($placeholder)")->execute(array_values($data));

作者:T&D
Q Q:335749143
邮箱:tanda.arch#gmail.com(@替换#)
出处:http://www.cnblogs.com/one-villager/
* 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/one-villager/p/7574711.html