关于小米
27岁,山西运城人,职业电商经理人,前端开发工作者,从事过网站建设、网络推广、SEO、SEM、信息流推广、二类电商、网络运维、软件开发,等相关电商工作,经验较为丰富,小米技术社区致力于为广大从事Web前端开发的人员提供一些力所能及的引导和帮助 ...[更多]
E-mail:mzze@163.com
Q Q:32362389
W X:xiaomi168527
关于王飞
27岁,山西运城人,职业电商经理人,网络工程师兼运维,从事过运营商网络建设,企业网络建设、优化。数据中心网络维护等通过,经验丰富,座右铭:当自己休息的时候,别忘了别人还在奔跑。 ...[更多]
关于小艳
大于花一样的年龄,河南郑州是我家,2010年在北京接触团购网,2011年进入天猫淘宝一待就是四年,如今已经将设计走向国际化(ps:误打误撞开始进入阿里巴巴国际站的设计,嘿嘿)五年电商设计,丰富经验,从事过天猫淘宝阿里各项设计,店铺运营,产品拍摄;我将我的经历与您分享是我的快乐!座右铭:越努力越幸运! ...[更多]
E-mail:97157726@qq.com
Q Q:97157726
PDO就是PHP data Object 提供了PHP操作多种数据库的统一的接口
PDO(PHP Data Object)扩展为PHP访问各种数据库提供了一个轻量级,一致性的接口。无论访问什么数据库,都可以通过一致性的接口去操作。
PDO是PHP5新加入的一个重大功能,我们的数据库服务器为MySQL,所有的程序代码的数据库操作全是一mysql()或者mysqli()函数来操作,当我们的数据库 需要更换时比如换成,SQL、SERVER、PostgreSQL、MS 等,我们不可能去修改所有的程序代码!所以就要用到PDO,PDO很好的帮我们解决了这个问题,使用PDO操作非常方便,只需要修改数据源格式,和加载相应的驱动文件到PHP.ini即可;

案例:连接mysql数据库方式
方法一:mysql扩展【这种方式php7已经淘汰】
方法二:mysqli扩展
方法三:PDO扩展
开启PDO连接MySQL扩展
extension=php_pdo_mysql.dll
1)编码的一致性
由于PHP可用的各种数据库扩展是由不同发行者编写的,所以尽管所有的扩展都提供了基本相同的特性,却不 满 足编码的一致性。PDO消除了这种不一致,提供了可用于各种数据库的单一接口;
2)灵活性
因为PDO在运行时加载必须的数据库驱动程序,所以不需要在每次使用不同数据库时重新配置和重新编译PHP。例如,如果数据库需要从SQL切换到MySQL,只需要加载PDO_MYSQL驱动程序就可以了。
3)面向对象特性
PDO利用PHP5的面向对象特性,可以获得更强大、更高效的数据库通信。
4)高性能
PDO是用C编写的,编译为PHP,与用PHP编写的其他解决方案相比,虽然其他都相同,但提供了更高的性能。
1、PDO类:表示PHP和数据库之间的一个连接
2、PDOStatement 类
第一:表示执行数据查询语句(select ,show)后的相关结果集
第二:预处理对象
3、PDOException类:表示PDO的异常

语法
__construct($dsn,用户名,密码)
DSN:data source name,数据源名称,包含的是连接数据库的信息,格式如下:
$dsn=数据库类型:host=主机地址;port=端口号;dbname=数据库名称;charset=字符集
数据库类型:
MySQL数据库 => mysql: oracle数据库 => oci: SQL Server =>sqlsrv: 具体驱动类型参见手册“PDO驱动”
实例化PDO的过程就是连接数据库的过程
<?php
$dsn='mysql:host=localhost;port=3306;dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
var_dump($pdo); //object(PDO)#1 (0) { }注意事项
1、如果连接的是本地数据库,host可以省略
<?php
$dsn='mysql:port=3306;dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
var_dump($pdo); //object(PDO)#1 (0) { }2、如果使用的是3306端口,port可以省略
<?php
$dsn='mysql:dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
var_dump($pdo); //object(PDO)#1 (0) { }3、charset也省略,如果省略,使用的是默认字符编码
<?php $dsn='mysql:dbname=data'; $pdo=new PDO($dsn,'root','root'); var_dump($pdo);
4、dbname也可以省略,如果省略就没有选择数据库
<?php $dsn='mysql:'; $pdo=new PDO($dsn,'root','root'); var_dump($pdo);
5、host、port、dbname、charset不区分大小写,没有先后顺序
6、驱动名称不能省略,冒号不能省略(因为冒号是驱动名组成部分),数据库驱动只能小写
方法:$pdo->exec($sql),执行数据增、删、改语句,执行成功返回受影响的记录数,如果SQL语句错误返回false。
<?php
//1、实例化PDO
$dsn='mysql:host=localhost;port=3306;dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
//2执行数据操作语句
//2.1 执行增加
/*
if($pdo->exec("insert into news values (null,'bb','bbbbbb',unix_timestamp())"))
echo '自动增长的编号是:'.$pdo->lastInsertId (),'<br>';
*/
//2.2 执行修改
//echo $pdo->exec("update news set title='静夜思' where id in (3,4)");
//2.3 执行删除
//echo $pdo->exec('delete from news where id=5');\
//2.4 完善
$sql="update news set title='静夜思1' where ids in (3,4)";
$rs=$pdo->exec($sql);
if($rs){
echo 'SQL语句执行成功<br>';
if(substr($sql, 0,6)=='insert')
echo '自动增长的编号是:'.$pdo->lastInsertId (),'<br>';
else
echo '受到影响的记录数是:'.$rs,'<br>';
}elseif($rs===0){
echo '数据没有变化<br>';
}elseif($rs===false){
echo 'SQL语句执行失败<br>';
echo '错误编号:'.$pdo->errorCode(),'<br>';
//var_dump($pdo->errorInfo());
echo '错误信息:'.$pdo->errorInfo()[2];
}方法:$pdo->query($sql),返回的是PDOStatement对象
<?php
$dsn='mysql:dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
//1、执行数据查询语句
$stmt=$pdo->query('select * from products');
//var_dump($stmt); //object(PDOStatement)
//2、获取数据
//2.1 获取二维数组
//$rs=$stmt->fetchAll(); //默认返回关联和索引数组
//$rs=$stmt->fetchAll(PDO::FETCH_BOTH); //返回关联和索引数组
//$rs=$stmt->fetchAll(PDO::FETCH_NUM); //返回索引数组
//$rs=$stmt->fetchAll(PDO::FETCH_ASSOC); //返回关联数组
//$rs=$stmt->fetchAll(PDO::FETCH_OBJ); //返回对象数组
//2.2 获取一维数组,匹配完成后指针下移一条
//$rs=$stmt->fetch(); //关联和索引数组
//$rs=$stmt->fetch(PDO::FETCH_NUM); //索引数组
//例题:通过while循环获取所有数据
/*
while($row=$stmt->fetch(PDO::FETCH_ASSOC)){
$rs[]=$row;
}
echo '<pre>';
var_dump($rs);
*/
//3.3 匹配列:匹配当前行的第n列,列的编号从0开始,匹配完毕后指针下移一条
//echo $stmt->fetchColumn(); //获取当前行的第0列
//echo $stmt->fetchColumn(1); //获取当前行的第1列
//3.4 总行数,总列数
/*
echo '总行数:'.$stmt->rowCount(),'<br>';
echo '总列数:'.$stmt->columnCount();
*/
//3.5 遍历PDOStatement对象(PDOStatement对象是有迭代器的)
foreach($stmt as $row){
echo $row['proname'],'-',$row['proprice'],'<br>';
}stdClass类是所有PHP类的父类
事务:是一个整体,要么一起执行,要么一起回滚
事务的特性:原子性,一致性,隔离性,永久性
需要将多个SQL语句作为一个整体执行,就需要使用到事务
语法
start transaction 或 begin 开启事务 commit 提交事务 rollback 回滚事务
案例:
创建测试数据
create table bank(
cardid char(4) primary key comment '卡号',
balance decimal(10,2) not null comment '余额'
)engine=innodb charset=utf8 comment '银行卡号表'
insert into bank values ('1001',1000),('1002',1)PDO操作事务
<body>
<?php
if(!empty($_POST)){
$dsn='mysql:dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
$out=$_POST['card_out']; //转出卡号
$in=$_POST['card_in']; //注入卡号
$money=$_POST['money']; //金额
$pdo->beginTransaction(); //开启事务
//转账
$flag1=$pdo->exec("update bank set balance=balance-$money where cardid='$out'");
$flag2=$pdo->exec("update bank set balance=balance+$money where cardid='$in'");
//查看转出的账号是否大于0,大于0返回true,否则返回false
$stmt=$pdo->query("select balance from bank where cardid='$out'");
$flag3=$stmt->fetchColumn()>=0?1:0;
if($flag1 && $flag2 && $flag3){
$pdo->commit (); //提交事务
echo '转账成功';
}
else{
$pdo->rollBack (); //回滚事务
echo '转账失败';
}
}
?>
<form action="" method="post">
转出卡号: <input type="text" name="card_out" id=""> <br>
转入卡号: <input type="text" name="card_in" id=""> <br>
金额:<input type="text" name="money" id=""> <br>
<input type="submit" value="提交">
</form>
</body>运行结果

小结:
$pdo->beginTransaction() 开启事务 $pdo->commit () 提交事务 $pdo->rollBack() 回滚事务
预处理好处:编译一次多次执行,用来解决一条SQL语句多次执行的问题,提高了执行效率。
预处理语句
prepare 预处理名字 from 'sql语句'
执行预处理
execute 预处理名字 [using 变量]
<?php
$dsn='mysql:dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
//创建预处理对象
$stmt=$pdo->prepare("insert into bank values (?,?)"); //?是占位符
//执行预处理
$cards=[
['1003',500],
['1004',100]
];
foreach($cards as $card){
//绑定参数,并执行预处理,
//方法一:
/*
$stmt->bindParam(1, $card[0]); //占位符的位置从1开始
$stmt->bindParam(2, $card[1]);
$stmt->execute(); //执行预处理
*/
//方法二:
/*
$stmt->bindValue(1, $card[0]);
$stmt->bindValue(2, $card[1]);
$stmt->execute();
*/
//方法三:如果占位符的顺序和数组的顺序一致,可以直接传递数组
$stmt->execute($card);
}<?php
$dsn='mysql:dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
//创建预处理对象
$stmt=$pdo->prepare("insert into bank values (:p1,:p2)"); //:p1,:p2是参数占位符
//执行预处理
$cards=[
['p1'=>'1003','p2'=>500],
['p1'=>'1004','p2'=>1000]
];
foreach($cards as $card){
//方法一:
/*
$stmt->bindParam(':p1', $card['p1']);
$stmt->bindParam(':p2', $card['p2']);
$stmt->execute();
*/
//方法二:但数组的下标和参数名一致的时候就可以直接传递关联数组
$stmt->execute($card);
}小结:
1、?是位置占位符
2、参数占位符以冒号开头
3、$stmt->bindParam()和$stmt->bindValue()区别

4、预处理的好处
a)提高执行效率
b)提高安全性
<?php
try{
$dsn='mysql:dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
//这是PDO错误模式属性,PDO自动抛出异常
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->query('select * from newsssssss'); //自动抛出异常
} catch (PDOException $ex) {
echo '错误信息:'.$ex->getMessage(),'<br>';
echo '错误文件:'.$ex->getFile(),'<br>';
echo '错误行号:'.$ex->getLine();
}小结:
1、PDOException是PDO的异常类
2、实例化PDO会自动抛出异常
3、其他操作不会抛出异常,需要设置PDO的异常模式
4、PDO异常模式
PDO::ERRMODE_EXCEPTION 抛出异常 PDO::ERRMODE_SILENT 中断 PDO::ERRMODE_WARNING 警告

本站内容均为小米原创,转载请注明出处:小米技术社区>> PHP的PDO,PDO的使用场景和其优点;实例化PDO;执行语句,操作事务,操作预处理,异常处理