PDOException 异常处理|学习笔记

简介: 快速学习 PDOException 异常处理

开发者学堂课程【PHP 进阶教程-由浅入深掌握面向对象开发-第三阶段PDOException 异常处理】学习笔记,与课程紧密联系,让用户快速学习知识。  

课程地址:https://developer.aliyun.com/learning/course/713/detail/12742


PDOException 异常处理

 

1、目标

本节目标掌握PDO中异常的实际使用,能够使用这种PDO的异常机制来封装代码的一个异常处理。

2、概念

PDOException:是PDO从exception继承的一个用于专门用于处理PDO中错误的异常类,一般如果做一套扩展都会去继承Exception来实现一套明确的错误机制(错误来自哪里),哪里我们要去做这件事情,然后要使用PDOException异常处理需要,设定PDO的错误模式为异常模式。

在PDO中可以通过两种模式来实现异常模式的设定。

(1):在初始化PDO对象的时候,利用第四个参数驱动来实现

(2):在初始化PDO之后,利用PDO::set Attribute()方法来修改错误模式。

3、步骤

演示具体步骤:

(1):第一个确定使用PDO异常来处理错误。

(2)第二个设定错误模式为异常模式

(3)第三个关键点,在可能出现错误的地方捕捉异常,使用PDOException类来实现。

4、示例

具体的示例:

设定异常模式,利用PDO::_construct()构造方法的第四个参数或者在实例化PDO之后,利用PDO::set Attribute()方法设置。

先使用构造方法的第一种方式:

$drivers=array(

#可以设置多种驱动(属性设置)

PDO::ATT_ERRMODE=> PDO::ERRMODE_EXCEPTION

);$pdo=newPDO(_’mysql:host=locallhost;port=3306;dbname=db_2’’root’,’root’,$drivers);

//增加一个驱动,里面增加一个属性,属性的下标,为PDO::ATT_ERRMODE,然后指向PDO::ERRMODE_EXCEPTION这个定义常量,把它弄好之后,放到我们的第四个参数里面就可以实现。下面编写代码进行实际操作:第一步实例化,用这种初始化的方式增加一个属性,其实就相当于它做完之后,后续做了一个PDO::set Attribute,即错误模式等于异常模式(PDO::ATT_ERRMODE= PDO::ERRMODE_EXCEPTION),这样就得到了一个异常模式的PDO,后续的所有操作它都应该是用异常来捕捉错误,确定了使用异常模式处理之后,其实就可以针对出错的位置使用异常来进行捕捉。比如在执行 SQL 的时候,很有可能会出现这种异常处理,比如要设置字符集,假设没在上面做,这个时候需要调用exec执行SQL,SQL属于人为可写的,通常这个字符集的来源是外部传入的,那么不能保证它的完全正确,怎么办呢?异常捕捉,但是捕捉都必须使用try catch来捕捉,捕捉好了之后,就使用PDO::ERRMODE_EXCEPTION类的对象来进行具体的处理,因为它报出的错误都会是产生一个PDO::ERRMODE_EXCEPTION的对象,来证明一下,把这个代码复制过来放到指定地方进行运行:

#执行SQL

try{

$pdo->exec(‘set names utf-8’); #错误

}catch(PDOException $e){

echo ‘SOL执行错误!<br/>‘;

echo ‘错误文件为:’.$e->getFile().’<br/>’;

echo ‘错误行号为:’.$e->getLine().’<br/>’;

echo ‘错误描述为:’.$e->getMessage();die();

}

//凡是执行SQL的地方,都有可能出现异常,用set names utf-8进行捕捉,看一下效果:

image.png这个时候就按照我们的指定的方式来做的,这就是异常模式,那当然可以做得更优雅的处理,不是这样直接报错,因为用户无所谓,那么作为开发阶段,可以用这种方式。但是如果是生产阶段,就是我们投入使用了,就应该写入到错误日志一样,供我们运维的人,或者说开发的人来实现这种什么判定或者说错误的一个检查,修正我们的一个代码,那这个我们就知道应该怎么用,如果说这个地方本身假设我抛出的一个throw new Exception(‘异常’)这样的异常,出现的效果:

image.png

它是把这个变成警告模式了,并没有去按照我们的方式来处理,是因为产生的这个exception类的一个对象,但是你这边捕获的却是一个PDO的,相当于它的一个子类的对象,你是捕获不到的。但是如果说我们这个地方再换一个,再换一个思路,把catch(PDOException $e)改为catch(Exception $e),观察能否捕获到。image.png

结果是可以捕获到,那个这又是什么样的逻辑?

image.png原因其实很简单,PDOException类的一个对象,本身是从Exception这里面继承的,所以它本身也是属于Exception对象,是跟它相关的,因此上级捕获下级可以捕获,但是如果是下级捕获上级,那么就捕获不了,所以这是它们的一个过程,在实际使用的时候,肯定是,谁报的什么对象错误,用什么来捕获,我们就用哪个地方来捕获这个数据,并且处理。那么从PDO的一个执行来讲,pdo异常模式的设置是在PDO实例化之后,但如果PDO实例化的时候就错误,那么PDOException就无法工作,因为我们先实例化PDO,然后再相当于设置了它的模式为异常模式,那么我们的PDO开发团队也其实考虑这个问题,PDO实例化之后本身是可以用try{]catch(){]来捕获的,我们要做的事情是使用先天异常捕捉实例化的错误,加一个try。

try{$pdo=newPDO(_’mysql:host=locallhost;port=3307;dbname=db_2’’root’,’root’,$drivers);

}catch(PDOException $e){

echo ‘实例化PDO错误!<br/>’;

echo ‘错误文件为:’.$e->getFile().’<br/>’;

echo ‘错误行号为:’.$e->getLine().’<br/>’;

echo ‘错误描述为:’.$e->getMessage();

die();

}

#执行SQL

try{

$pdo->exec(‘set names utf-8’); #错误

}catch(PDOException $e){

echo ‘SOL执行错误!<br/>‘;

echo ‘错误文件为:’.$e->getFile().’<br/>’;

echo ‘错误行号为:’.$e->getLine().’<br/>’;

echo ‘错误描述为:’.$e->getMessage();

die();

}

如果把3306改为3307。

image.png

运行之后的结果:image.png显示实例化PDO错误,同时出现了一个很典型的问题,报出乱码错误信息,应该是什么积极拒绝之类的信息,那说明这个信息依然有可能是中文,应该怎么办?把echo ‘错误描述为:’.$e->getMessage();

改为echo ‘错误描述为:’.iconv($e->getMessage());通过这个其实也可以思考一下,PDO的底层应用的是什么,用的是一套跟my SQL i扩展一样的一套底层来实现的。所以没有注意到这个中文问题,echo ‘错误描述为:’.iconv($e->getMessage());改ech’o错误描述 为:’.iconv(_’gbk’,’utf-8’,$e->getMessage());,再一刷新,看一下效果:

image.png乱码部分显示积极拒绝,所以这个地方要注意细节的问题,细节问题描述一下,因为连接错误,还没有设置好字符集,系统返回的信息字符集为GBK。做好之后我们该做的事情,其他的该捕获就捕获,但是在捕获的过程中,有时还要考虑一个问题,如果业务真的没有办法往下面执行,意外逻辑无法继续,可以主动抛出异常,就是throw new PODException,比如说我们在写的过程中,我们执行的操作执行完之后发现,我要获取他的ID这个业务需求,而获取的时候发现没做到,那么我们该怎样?应该抛出这个异常,因为外部用这个ID肯定用来干事情的,我没有拿到,我应该怎么把这个东西给他,怎么样给他抛出来,去捕获这个数据,这就是我们的一个主动抛出异常。

#抓异常

try{

$pdo->exec(‘insert into t_40 values’);

$id = $pdo->lastInsertID();

If(!$id) throw new PDOException(‘没有拿到自增ID:插入失败’);

}catch(PDOException $e){

echo ‘SOL执行失败!<br/>‘;

echo ‘错误文件为:’.$e->getFile().’<br/>’;

echo ‘错误行号为:’.$e->getLine().’<br/>’;

echo ‘错误描述为:’.$e->getMessage();

die();

}

这个是主动捕捉异常,判定数据执行的时候,发现逻辑问题无法继续。或者说无法为后面的一个业务提供支持了,我们就应该让他报错,前面的代码都让它变好之后,后面他能不能主动起来,这个代码是可以放到一起try,没必要try这么多次,我们会发现,这个代码都可能有错,可以放在一起try。

image.png运行结果如下图:

image.png分析一下,捕获到了错误信息,语法错误首先捕捉到了,是因为这个地方是不是本身有问题,如果是我们操作的过程中本身成功了,成功了,但是没有注册ID,比如说我当前是个‘select *from t_40’_操作就捕获一下,结果显示没有ID,因为这个逻辑它可以执行,只是它拿到的是一个行数,不要让它得到一个PDO的对象,所以没办法往下面真正地获取数据,这样可以主动控制,这是我们的一个逻辑。

总结:

1、PDOException是用来捕捉异常PDO(PDOStatement)类使用过程中产生的错误的

2、PDOException在使用之前必须要开启PDO异常模式,否则不能使用。其实PDO的实例化除外,因为它必须是最开始操作,所以系统考虑过它可以直接步骤,

3、像这种异常处理的模式有类似的相关性,会发现我们在处理的时候是不是给我一个对象,然后把错误捕获起来,那如果很多地方都用到try catch,进行封装直接调用即可,维护统一且方便。

4、PDOException一般是在SQL执行过程中出错,因为内部执行通常不会出现太多错误。不外乎就是你外部给的SQL有问题,或者你的逻辑有问题,让我出现错误,所以如果出现这种业务的话,我们应该怎么主动抛出异常,让他在往上面执行,因为它有可能支撑不了后续的业务。

相关文章
|
2月前
try...except异常处理
【10月更文挑战第16天】try except的一些异常处理方法
33 2
|
2月前
|
SQL Java 程序员
异常处理
【10月更文挑战第10天】
13 2
|
3月前
|
Python
ython之对异常处理
ython之对异常处理
|
7月前
|
C++
C++程序异常处理
C++程序异常处理
44 1
|
7月前
|
C++
11. C++异常处理
11. C++异常处理
45 0
11. C++异常处理
|
7月前
|
存储 安全 Java
【C++】—— 异常处理
【C++】—— 异常处理
|
7月前
|
C++
C++异常处理详解
C++异常处理详解
38 0
|
Java 编译器 C++
C++异常处理
C++异常处理
39 0
C++学习笔记_10 异常处理 2021-04-27
C++学习笔记_10 异常处理 2021-04-27
C++——异常处理
C++——异常处理
101 0
C++——异常处理