PDO提供了一套帮助用户实现多种数据库操作的统一接口
加载·
首先需要在php.ini文件加载需要使用的数据库拓展库 以mysql为例
去掉 ;exrtension =pdo_mysql前面的注释即可 然后重启apache就成功加载了
PDO
PDO主要由 PDO PDOStatement PDOException三个类组成
PDO PHP DATA OBECT 是一种纯面向对象的数据库操作拓展
PDO方法
构造函数 __construct($dsn,$user,$pass,$drivers);
$dsn : 驱动名字 例如 mysql
驱动选项 例如 localhost
端口 例如 3306
数据库名字 例如 test;
$user 用户名 例如 root
$pass 密码 例如 root
$drivers 驱动信息 例如更改PDO的报错模式(可不传入)
实例化:new Pdo("mysql:host =localhost;port=3306;dbname=syudyphp","root",980613);
写操作:exec(sql)
返回一个受影响的行数 如果发生错误返回false
读操作query(sql);
返回一个PDOStatement对象
利用pdostatement对象中的fetch()/fetchAll方法 可以得到返回的数组 通常传入参数PDO::MYSQL_ASSOC
使输出关联数组
错误编号 errorcode
返回当前操作的错误编号
错误信息 errorinfo
返回一个索引数组 错误代码 驱动代码 错误信息
<?php
#实例化PDO对象
$dsn = "mysql:host=localhost;port=3306;dbname=studyphp";
$user="root";
$pass="980613";
$p = @new PDO($dsn,$user,$pass);//返回一个PDO对象
#写操作
$sql = "delete from student where id =7 ";
$res = $p->exec($sql);
var_dump($res);//int(1)
#读操作
$sql ="select*feom student";
$statements = $p->query($sql);
var_dump($p);//object(PDO)#1(0){}
; ?>
是开发中通常对PDO进行二次封装
PDO能独立的完成写的操作
<?php
#注册认证函数
function pdo_init(){
$p = new PDO("mysql:host=localhost;port=3306;dbname=studyphp","root","980613");
if(!$p){
echo "连接认证失败".$p->errorInfo()[2];
exit;
}
return $p;
}
#写操作
function pdo_exec1($p,$sql){
$res = $p->exec($sql);
if($res===false){
echo "数据库语句执行失败","<br/>";
echo "错误代码为".$p->errorcode();
echo "错误信息为".$p->errorInfo()[2];
}
return $res;
}
#读操作
function pdo_query($p,$sql,$all=true){
$s = $p->query($sql);
if(!$s){
echo "数据库语句执行失败","<br/>";
echo "错误代码为".$p->errorcode();
echo "错误信息为".$p->errorInfo()[2];
}
if($all){
return $s->fetchAll(pdo::FETCH_ASSOC);
}else{
return $s->fetch(PDO::FETCH_ASSOC);
}
}
#返回自增长 id
function getId($p){
return $p->lastInsertid();
//返回当前插入的自增长id
}
#测试代码
$p = pdo_init();
$sql = "delete from student where id = 8";
pdo_exec1($p,$sql);
echo getId($p);
$sql = "select * from student ";
$res= pdo_query($p,$sql);
echo "<pre/>";
var_dump($res);
/*0
array(3) {
[0]=>
array(3) {
["id"]=>
string(1) "9"
["name"]=>
string(3) "ada"
["age"]=>
string(2) "10"
}
[1]=>
array(3) {
["id"]=>
string(2) "10"
["name"]=>
string(3) "bob"
["age"]=>
string(2) "12"
}
[2]=>
array(3) {
["id"]=>
string(2) "11"
["name"]=>
string(5) "condy"
["age"]=>
string(2) "13"
}
}*/
?>
事务处理
PDO封装了一些提供失误处理的方法 当然本质上还是执行execsql语句
开启事务beginTransaction
执行代码
成功提交commit
失败回滚 rollback
设置回滚exec(savepoint sp1)
回到回滚点 exec(rollback to sp1)
PDOExceptio
不仅过设置的异常处理机制是一种所见即所得 对用户体验来说很不友好
Exception是面向对象中一种错误的捕捉机制
捕捉执行层的问题
<?php
set_error_handler(function(){
throw new Exception("发生错误");
});
#告诉系统不要直接报错
try{
echo $res = 4/0;//发生错误
}catch(Exception $e){
echo $e->getmessage();
}
?>
PDO有一个专门处理异常的类 PDOException
PDO有三种错误处理机制 分别是
PDO::ERRMODE_SILENT 默认静默模式 不报错
PDO::ERRMODE_WARING 直接报错
PDO::ERRMODE_EXCEPTION 异常处理模式 处理异常
<?php
try{
$p = new PDO("mysql:host=localhost;port=3306;dbname=studyphp","root",980613);
if(!$p){
throw new Exception("连接认证失败");
}
}catch(Exception $e){
#由于用户传入数据而产生的不可意料的错误 要抓取
echo "sql连接出错","<br/>";
echo $e->getMessage(),"<br/>";
}
$p->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
#更改模式
#异常处理函数
function getException($pdo,$sql){
try{
$res = $pdo->exec($sql);
//可以在编写代码时就可以意料到的错误可以主动抛出
if(!$res){
throw new Exception("sql语句执行错误");
}
}catch(Exception $e){
#由于用户传入数据而产生的不可意料的错误 要抓取
echo "sql语句出错","<br/>";
echo $e->getMessage(),"<br/>";
}
}
$sql = "update student set age =88 where id = 10";
getException($p,$sql);
?>
总之来说在编码时可以预见的错误就经判断后主动抛出throw new Exceprion(错误信息)
然后由于客户操作而不可预知的错误由系统抓取 getMessage可以获得上面的错误信息
预处理
当sql语句重复性比较大时 预处理机制可以提高效率
prepare
提交预处理代码 一般里面都会有占位符才有意义
execute
执行预处理代码 一般都会用到use给占位符赋值才有意义 use后必须是个变量
drop
删除预处理
prepare 预处理名字 from '预处理语句';
PDO本身提供了一套预处理机制
prepare()
参数为sql语句 成功返回PDOStatement 对象 失败返回false
bindvlaue
第一个参数为占位符 ?/:name 后者不要考虑先后顺序 第二个参数是变量的值 或者另一个变量 此方法的传入的即使是变量 也只是获得变量的值 以后变量改变也不会影响值
bindparam
第一个参数为占位符 第二个参数必须为变量引用 引用传递
```execute``执行 如果执行语句时查询 结果会返回到对象之中
<?php
#准备sql语句
$p = new PDO("mysql:host=localhost;port=3306;dbname=studyphp","root",980613);
$sql = "select *from student where id between :min and :max "; //:name 的形式相当于?不用考虑位置的问题
#发送预处理
$s = $p->prepare($sql);
#绑定预处理参数
$s->bindValue(':min',9);
$s->bindValue(':max',14);
#执行预处理
$s->execute();
echo "<pre/>";
$res = $s->fetchAll(PDO::FETCH_ASSOC);
var_dump($res);
?>
PDO二次封装
二次封装 简化操作 提高用户体验
<?php
#二次封装PDO
#核心类
namespace core;
#把全局空间的类引入进来
use \PDO,\PDOStatement,\PDOException;
use Exception;
class Dao{
#PDO对象会经常在其他方法中使用 封装一个函数、
private $pdo;
private $fetch_mode;
public function __construct($info=array(),$drivers=array()){
$type = $info['type'] ?? 'mysql';
$host = $info['host'] ?? "localhost";
$port = $info['port'] ?? '3306';
$dbname = $info['dbname'] ?? 'studyphp';
$user = $info['user'] ?? 'root';
$pass = $info['pass'] ?? '980613';
$charset = $info['charset'] ?? 'utf8';
$this->fetch_mode=$info['fetch_mode'] ?? PDO::FETCH_ASSOC;
$driver['PDO::ATTR_ERRMODE'] = $drivers['PDO::ATTR_ERRMODE'] ?? 'PDO::ERRMODE_EXCEPTIOPN';
$dsn = $type.':'.'host='.$host.';port='.$port.';dbname='.$dbname;
#实例化时候传入两个数组 也可以不传
#第一个数组包含各种数据库信息 type host port dbname user pass charset fetch_mode
#第二个数组传入驱动信息
#实例化
try{
$this->pdo = new PDO($dsn,$user,$pass,$driver);
}catch(Exception $e){
echo "对不起 连接认证失败";
exit;
}
#设置字符集
try{
$this->pdo->exec("set names {$charset}");
}catch(Exception $e){
echo "对不起 设置字符集出错";
exit;
}
}
#执行写操作
public function dao_exec($sql){
try{
$row =$this->pdo->exec($sql);
return $row ; //返回受影响行数
}catch(Exception $e){
echo "对不起 sql语句执行错误","<br/>";
echo $e->getMessage();
exit;
}
}
#获取自增长id
public function getlastid(){
return $this->pdo->lastInsertId();
}
#读操作
public function dao_query($sql,$all=true){
try{
$stam = $this->pdo->query($sql);
}catch(Exception $e){
echo "对不起 查询数据失败";
}
if($all){
return $stam->fetchAll($this->fetch_mode);
}else{
return $stam->fetch($this->fetch_mode);
}
}
}
$d = new Dao();
/*$sql = "insert into student values(4,'ses',56)";
$d->dao_exec($sql);
echo $d->getlastid();*/
$sql = "select * from student";
$res = $d->dao_query($sql,FALSE);
echo "<pre/>";
var_dump($res);
?>