PDO概述
数据库有很多种,MySQL、sqserver、Oracle、db2......通过PHP去连接数据库的时候使用的扩展是不一样的,这就导致更换数据库时比较麻烦,因为不同扩展库的API不同,代码逻辑、函数需要更改......那么有没有一套扩展库可以直接用来连接所有的数据库呢?有,就是PDO(php data object)
百度释义:PDO(PHP Data Objects)是一种在PHP里连接数据库的使用接口。PDO与mysqli曾经被建议用来取代原本PHP在用的mysql相关函数,基于数据库使用的安全性,因为后者欠缺对于SQL注入的防护。
图示:
在info中查看已安装的
wamp PHP扩展启用:
PDO的使用
主要是这三个类 PDO、PDOStatement、PDOException
dsn(data source name)
数据源名称或叫做 DSN,包含了请求连接到数据库的信息。通常,一个 DSN 由 PDO 驱动名、紧随其后的冒号、以及具体 PDO 驱动的连接语法组成。
创建PDO对象
PDO::__construct ( string $dsn
[, string $username
[, string $password
[, array $driver_options
]]] )
创建一个表示连接到请求数据库的数据库连接 PDO 实例。
<?php
$dsn = 'mysql:dbname=pdo_demo;host:localhost;charset=utf8';
//这里我将host放在了紧挨着mysql后边,数据库连接没问题,但是在之后的执行sql语句中报了错:
//SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected
//将dbname前移就好了,手册里有讲,难道版本升级后顺序变了?
try {
$pdo = new PDO($dsn, 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die('数据库连接失败:'.$e->getMessage());
}
1、字符串形式:'mysql:host:localhost;dbname=pdo_demo;charset=utf8';
2、文件形式:uri:file:///path/to/dsnfile
3、php.ini
获取和设置信息
PDO::getAttribute — 取回一个数据库连接的属性
PDO::setAttribute — 设置属性
PDO执行sql语句
- exec 执行不要结果集的语句 比如:增删改
- query 执行要结果集的语句 比如:插 desc
- lastInsertId 最后插入语句的id号
PDO错误模式
1、默认
2、警告:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
3、异常:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
<?php
$dsn = 'mysql:dbname=pdo_demo;host:localhost;charset=utf8';
try {
$pdo = new PDO($dsn, 'root', '');
//在创建完PDO对象的时候设置错误模式
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die('数据库连接失败:'.$e->getMessage());
}
try {
$sql = 'insert into user(name, pwd) values("fmujie", "123456")';
$ret = $pdo->exec($sql);
if ($ret > 0) {
echo '插入成功';
//返回插入的id索引
echo $pdo->lastInsertId();
} else {
echo '插入失败';
}
} catch (PDOException $e) {
echo $e->getMessage();
}
查询
PDO::query() returns a PDOStatement object, or FALSE
on failure.
try {
$sql = 'select * from user';
$ret = $pdo->query($sql);
var_dump($ret);
} catch (PDOException $e) {
echo $e->getMessage();
}
PDO的事务处理
比如:转账 A转出和B转入要都正确无误,否则交易失败(把多条sql语句作为一个整体(事务)来执行,如果其中有一条sql语句执行失败,所有的sql语句都要执行失败,将状态回滚到初始状态)
表的引擎有两种 myisam (不支持) innodb(支持)
$pdo->beginTransaction(); 开启一个事务//在执行sql语句之前
$pdo->commit(); 提交事务
$pdo->rollback(); 回滚到初始状态
try {
$pdo->beginTransaction();
$sql = '';
$ret = $pdo->exec($sql);
if ($ret > 0) {
echo '执行成功';
//返回插入的id索引
echo $pdo->lastInsertId();
} else {
throw new PDOException('执行失败');
}
$sql = '';
$ret = $pdo->exec($sql);
if ($ret > 0) {
echo '执行成功';
//返回插入的id索引
echo $pdo->lastInsertId();
} else {
throw new PDOException('执行失败');
}
$pdo->commit();
echo '执行都成功';
} catch (PDOException $e) {
$pdo->rollback();
echo $e->getMessage();
}
预处理语句
优点
- 效率
- 安全(sql注入)
平差我们每插入一条语句便写一条insert的sql语句,php每次都得编译生成,这样重复的向同一个表中插入语句会造成很大的资源浪费。使用预处理语句对于相同的sql语句,在值的部分使用占位符,这样在程序编译的时候只需要编译一条sql语句,Then以下添不同的值就ok了,这样的效率无疑会提升许多。
PDOStatement::bindParam — 绑定一个参数到指定的变量名
parameter
参数标识符。对于使用命名占位符的预处理语句,应是类似 :name 形式的参数名。对于使用问号占位符的预处理语句,应是以1开始索引的参数位置。
增删改
增加:
$stmt = $pdo->prepare('insert into user(name, pwd) values(?, ?)')
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $pwd);
$name = '...';
$pwd = '...';
$stmt->execute();
//或者
$stmt = $pdo->prepare('insert into user(name, pwd) values(:name, :pwd)');
$stmt->bindParam(':name', $name);
$stmt->bindParam(':pwd', $pwd);
$name = '...';
$pwd = '...';
$stmt->execute();
//写起来比较麻烦,重复太多
$stmt->execute(['...', '...']); //?占位符使用索引数组
$stmt->execute([':name'=> '...', ':pwd'=> '...']); //:占位符使用关联数组
PDO提取结果集
select query()返回的 $ret
try {
$stmt = $pdo->prepare('select * from user');
$stmt->execute();
$res = $stmt->fetch();//默认是索引数组和关联数组都有 一条
$result = $stmt->fetchAll();//取出全部
var_dump($res);
} catch (PDOException $e) {
echo $e->getMessage();
}
控制下一行如何返回给调用者。此值必须是 PDO::FETCH_* 系列常量中的一个,缺省为 PDO::ATTR_DEFAULT_FETCH_MODE 的值 (默认为 PDO::FETCH_BOTH )。
• PDO::FETCH_ASSOC:返回一个索引为结果集列名的数组
• PDO::FETCH_BOTH(默认):返回一个索引为结果集列名和以0开始的列号的数组
• PDO::FETCH_NUM:返回一个索引为以0开始的结果集列号的数组
• PDO::FETCH_OBJ:返回一个属性名对应结果集列名的匿名对象
(常用)
还不快抢沙发