PDO概念
PHP和MySQL数据库是“黄金搭档”,但是能和PHP“搭档”的不止MySQL数据库一种,还有mssql、Oracle、SQLServer(局限:只能用微软开发的windows操作系统),每一种数据库都为PHP提供了属于自己的操作数据库的扩展函数!比如,就以连接数据库为例:
MySQL:mysql_connect
mssql:mssql_connect
Oracle:oci_connect
所以,如果PHP要切换不同的数据库,就要切换不同的数据库操作函数:
这样,无论从程序员学习的角度,还是从程序员开发的角度,都很麻烦!
于是PDO就问世了,能把对所有数据库都统一成相同的操作以实现相同的目的
PDO的全称是:PHP Data Object(PHP数据对象)
在新版本的PHP(PHP5以上)中,PHP为用户封装了一套PDO扩展库,专门用来操作不同类型的数据库!
同php需要开启MySQL扩展和GD库扩展一样,以前需要手动的在php.ini中开启PDO扩展,现在默认开启
1 | extension=php_pdo.dll 现在已经没有这行,默认开启pdo |
我们首先应该学习pdo的构造方法
1 | PDO::__construct(string $dsn[,string $username[,string $password[,array $driver _options]]]) |
dpo实现-增删改
dsn.pass);
$sql=“insert into student values(null,‘如来’,‘丽丽’)”;
pdo->exec($sql)
PDO::exec()在执行一条sql语句,返回受此语句影响的行数
PDO::lastInstertId([string $name=null]),返回最后插入的记录的主键id号
删除和更新,其实就是修改$sql语句就行了!
dpo实现-查
$sql=“select * from student”;
pdo->query($sql);//执行一条sql查询语句,返回一个PDOStatement类的对象,也叫作结果对象。
rowCount 获取查询结果中的总记录数(总行数)
columnCount 获取查询结果中的总字段数(总列数)
在实际的应用中,获取总记录数的操作比较多
fetch
每次从PDOStatement结果集中,获取一条记录,同时将指针下移,其中该方法有一个参数,可以控制返回值的类型!
PDO::FETCH_ASSOC返回一个关联型的数组,数组的下标就是字段的名字!效果类似于以前的mysql_fetch_assoc
PDO::FETCH_NUM 返回一 个索引数组,效果类似于以前的mysql_fetch_row
PDO::FETCH_BOTH 返回一个关联和索引并存的混合数组,也是缺省值!
PDO::FETCH_OBJ 返回一个对象,其中对象的属性就是字段的值!
FETCH_ASSOC使用最多,利用fetch方法实现对结果集的遍历!
1 | $rows=[]; |
fetchAll 返回一个结果集中所有的记录,形成一个二维数组,比较适合多行多列的结果集的提取
fetchcolumn 每次获取指定的某一列信息中的一条记录,并将指针下移!第一列参数为0,第二列为1,依次类推!例如:var_dump($stmt->fetchcolumn (5))可用于遍历
fetchobject 每次读取一条记录放到一个对象中,并使指针下移!
mysql、pdo的预处理技术
mysql
插入多条数据
1 | insert into php_student values(null,'孙悟空',''XXXX) |
每次执行的sql语句的命令和结构都是一样的,只是其中的数据不同,采用传统的执行方式,每次都必须传输整条sql语句,对于MySQL服务器而言,得到的每一次的命令都是全新,都是根据sql语句从0解析并执行!
(实际上我使用以下方法,照样一次执行,这里是做个历史介绍)
1 | INSERT INTO `yy_news`(`logo`, `title`, `keywords`, `digest`, `content`, `type`, `addtime`, `recommend`) VALUES ( 'kj', '设备', '45sjksdj', 'Shopset', 'printer',1, 56555448, 1),('kj2', '打备3', '45sjksdj', 'Shopset', 'printer',1, 56555448, 1); |
采用预处理机制优化
将前面相同的命令和结构部分发送给MySQL服务器,让MySQL服务器事先进行一次预处理(此时并没有真正的执行sql语句),而为了保证sql语句的结构完整性,在第一次发送sql语句的时候将其中可变的数据部分都用一个数据占位符来表示,比如问号?就是常见的数据占位符!
不带参数的预处理
1 | 1、准备预处理语句 |
传参的预处理
以之前不带参数的差不多,只是其中可变的数据部分用一个数据占位符来表示
1 | 1、准备预处理语句 |
PDO
基本的原理和mysql预处理都是一样的,只不过就是把前面所有命令行的语法封装成了PDO对象的几个公开的方法而已
1 | 1、发送预处理语句 |
PDO事务处理
student表有id/name/money字段
inster into student (id,name,money)values (1,‘张三’,2000),(2,'李四‘,7000);
线张三找李四借1000,则
update student set money=money-1000 where name=‘李四’;
update student set money=money+1000 where name=‘张三’;
update语句是两个独立的sql语句,MySQL服务器需要独立的执行两次!但是从业务逻辑上看,这两个sql语句必须全部执行成功整个业务逻辑才算是执行成功!只要有一个执行失败,就不符合正常的业务逻辑!
**事务:**将上面的两个操作(两个update)认为是一个事务,其中有任意一条语句执行失败,我们就认为整个事务执行失败!应该回滚“恢复”到最初的状态!**注意:**目前只有InnoDB引擎才支持事务处理
MySQL的事务处理
1 | 1、开启事务 |
**注意:**当我们开启一个事务的时候,我们对sql的操作都发生在内存中,但是没有真正的反馈到数据库磁盘的文件中!可以开启另外一个客户端进行查看数据,数据并没有变化,还是7000。所以,如果此时李四反悔了,可以进行回滚操作!
回滚事务
语法形式:rollback;
1 | mysql>rollback; |
所谓的事务的回滚,就是恢复到事务开启之前的最原始的状态!
**注意:**回滚操作会自动的关闭一个事务,如果想再次执行事务,需要重新开启事务!
1 | mysql>start transaction; |
1 | 3、执行事务 |
**原理:**普通的执行,之所以是立即执行并生效,因为默认的,MySQL对sql语句的执行是自动提交的!
所以,开启一个事务的本质,就是关闭了以前的自动提交的功能,而是由用户手动提交(利用commit语句)!
开启事务的另一种方式,关闭自动提交的功能关闭!
语法形式为:set autocommit = 0;
mysql>set autocommit = 0;
此时,每次执行sql语句都需要手动的进行提交
PDO的事务处理
基本原理和步骤其实都是一样的,就是调用PDO对象的三个方法:
开启事务:beginTransaction
回滚操作:rollBack
执行操作:commit\
1 | $pdo->beginTransaction(); |
PDO相关属性(参数)
虽然PDO所有的属性都不是public型,但是还是可以通过两个方法来设置和查看PDO的属性:
setAttribute:设置属性
getAttribute:获取数组的值
常见的属性:
PDO::ATTR_AUTOCOMMIT 自动提交,只有两个值:0或1
0不开启自动提交,手动提交(调用commit方法)
1开启自动提交,自动实现事务处理
PDO::ATTR_CASE:返回结果集的大小写,有三个值可以设置
CASE_LOWER:返回的结果集全部小写!
CASE_UPPER:返回的结果集全部大写!
CASE_NATURAL:返回的结果集正常(默认值,原来数据库中什么样现在返回的还是什么样)
1 | $pdo=new PDO($dsn,$user,$pass); |
PDO::ATTR_ERRMODE:返回的错误模式
pdo异常处理
异常的概念:
异常,其实就是错误,不过是在面向对象编程语言中的一种典型的错误处理方式!所谓的异常,就是把错误信息,放到一个 对象中!
但是,异常的发生有一个前提,就是必须保证语法是正确的!
异常的处理:
1 | 首先要发生异常! |
抛出异常,throw
抛出异常其实就是利用throw关键字来完成的,语法形式为:throw 异常;
注意:
这里的异常,其实就是一个异常对象,这个对象必须是由系统预定义的异常类(类名为Exception)或者其子类实例化出来的!
1 | class Goods { |
以上只是抛出了一个异常,并没有进行监听和捕获!(类比抛绣球招亲)
异常监听,try
利用关键字try可以监听一段有可能出现异常的代码内,来监听是否发生了异常!
语法为:try{被监听的代码段;}catch(){}
1 | try{//对代码进行监听 |
PDO中处理错误的方式,即设置PDO::ATTR_ERRMODE