《PHP精粹:编写高效PHP代码》——1.7节异常

简介:

本节书摘来自华章社区《PHP精粹:编写高效PHP代码》一书中的第1章,第1.7节异常,作者:(美)  Davey Shafik,更多章节内容可以访问云栖社区“华章社区”公众号查看

1.7 异常
异常(exception)是一个处理错误的面向对象方法。一些PHP扩展像往常一样仍会报错;很多最新的扩展(例如PDO)将代替抛出异常。异常也是对象,而且Exception是PHP的一个内置类。一个Exception对象将包含发生错误的位置(文件名或代码行)、一条错误消息和(可选)一个错误代码等信息。

1.7.1 处理异常
首先我们看看如何处理可能会抛出异常的函数。我们会使用一个PDO示例,因为PDO扩展抛出异常。在这里代码会试图创建一个数据库连接,但是会失败,因为nonsense主机不存在:


6a3ccbd06ac553073fc1365c40b1daa904741bfb


26e6dab245ebf5452b25d04274b1263b3f493c88

这段代码阐明了try/catch结构。在try块中,我们将想要的代码放到应用程序中运行,但我们知道代码可能会抛出一个异常。在catch块中,可以添加一些应对错误的代码,无论是处理它还是记录它,采取任何行动都是恰当的。
注意,当发生一个异常时,就像这里试图连接到数据库一样,PHP没有运行try块中其余的代码而直接跳转到catch块中。在这个示例中,数据库连接失败意味着我们根本看不到已连接到数据库的消息,因为这一行代码根本无法运行。
无finally子句
如果你在其他语言中使用过异常,你可能习惯于try/catch/finally结构;PHP没有附加的finally子句。

1.7.2 为什么要处理异常
比起会引发不同层次错误的传统方法,异常是一个更简洁的错误处理方法。在执行代码的过程中,我们可以根据错误的严重程度对异常做出反应。我们可以对问题进行评估,然后告诉系统如何恢复,或顺利地摆脱困境。
将所有的异常作为对象意味着我们可以扩展异常(很快会有示例演示),并且可以自定义异常的数据和反应。我们已经知道如何使用对象工作,这使得我们能更简单地把复杂功能添加到错误处理系统中。

1.7.3 抛出异常
我们已经看到如何处理由PHP内置函数抛出的异常,但是我们自己如何抛出异常呢?是的,我们肯定能够做到这一点:


88ae3f36e0312b5b04607d0247d22f354edb6be0

可根据需要为Exception类设置任何属性或添加任何方法。定义为一个空类也很常见,空类只是为了提供更多特定类型的异常,使我们识别出:应用程序的哪一部分遇到了问题而没有尝试以编程方式读取错误信息。
自动加载异常
此前,介绍了自动加载,为在哪里能找到类而定义规则,而在脚本中执行的代码并未包含这个类的定义。异常也是简单的对象,因此也可以使用自动加载功能来加载异常类。

通过所有特定的异常类可以捕捉不同的异常类型,将在下一节学习这一点。

1.7.5 捕捉特定类型的异常
思考如下这个代码示例可以抛出多个异常:


2df6f889373742de2950504cc819fb030836d2e0


5fdedfdc6242d5aceddb401836117b1a30f4b836

在这个示例中,开始实例化Courier和Parcel两个对象。Parcel对象既有地址又有重量;当发货的时候会检查它们。注意,这个示例使用了一个小小的rand()函数来产生各种包裹的重量!这是一个测试代码的有趣方法,因为有些包裹由于超重而引发异常。
在try块中,要求快递公司运送包裹。如果运气好,过程一切顺利,我们就会看到“parcel shipped”消息。这两个catch块让我们巧妙地处理失败结果,第一个catch块负责特定捕捉HeavyParcelException异常,任何其他类型的异常由第二个很普通的catch块捕捉。如果我们想首先捕捉Exception异常,所有的异常将最终在这里被捕捉,那么我们首先要保证这个catch块具有最特殊的异常类型。
实际上,这个catch块使用了类型提示来区分一个对象是否为可接受的类型。因此前面介绍的类型提示和多态性也适用于这里;一个HeavyParcelException异常也是一个Exception异常。
在这个示例中,异常从类的内部抛出,进而捕捉代码中调用对象方法的栈。没有捕捉到的异常会返回调用它的内容中,如果在这里它们仍然没有被捕捉,它们将继续通过调用栈向上抛出。当它们到达顶部仍然未被捕捉,我们将看到严重的错误:Uncaught Exception。

1.7.6 设定一个全局异常处理程序
为避免出现异常被抛出而代码捕捉失败的严重错误,可以为应用程序设定一个默认的行为。为做到这一点,使用了一个名为set_exception_handler()的函数。它接受一个回调作为它的参数,因此可以为使用的函数命名,例如,一个异常处理程序通常会在屏幕上给用户显示一个错误提示—这比一个严重错误的消息要好得多!
一个基本的异常处理程序类似于这样:


92997eacb8facbec36a9d6a51c9cc3d92ca75153

这里显示了一个异常处理程序,然后它调用set_exception_handler()方法注册这个函数来处理未捕获的异常。通常在脚本的开始部分声明和设置异常处理程序,或者放在引导文件中,如果你有一个的话。
默认错误处理
除了使用set_exception_hander()处理异常外,PHP也提供set_error_handler()方法处理错误。

示例异常处理程序使用error_log()函数在PHP的错误日志中写入错误的内容,打开日志文件会看到如下内容:


f1018da00d896adf5080ff51cae6623c9dade039

1.7.7 使用回调
刚才展示了回调函数的使用,正好我们可以看看是否还有其他可用的选择。回调广泛应用于PHP的各个方面,set_exception_handler()和set_error_handler()函数就是很好的例子。也可以使用回调,例如,在array_walk()这个函数中,要求PHP使用相同的操作,为一个数组中的每一个元素指定使用一个回调。
回调可以使用多种形式:
一个函数名
一个类名和一个方法名,其中方法是静态调用的
一个对象和一个方法名,其中调用的方法与提供它的对象相对应
一个closure(存储在变量中的一个函数)
一个lambda函数(就地声明的一个函数)
回调让我们使用匿名函数成为可能。为异常处理程序声明的匿名函数不会用于应用程序的任何其他地方,因此没必要为它取一个全局性的名称。在PHP手册的相关页面上还有更多关于匿名函数的内容。

相关文章
|
2月前
|
PHP 开发者
PHP中的命名空间:优雅解决代码冲突与组织结构
在PHP开发中,命名空间是一种重要的工具,可以帮助开发者避免代码冲突、提高代码组织结构和可读性。本文将深入探讨PHP中命名空间的概念、使用方法以及实际应用场景,帮助读者更好地理解和运用命名空间来优化他们的PHP代码。
拿php写个原生增删改查案例出来(提供全部代码+sql)
拿php写个原生增删改查案例出来(提供全部代码+sql)
拿php写个原生增删改查案例出来(提供全部代码+sql)
|
29天前
|
存储 运维 Serverless
函数计算产品使用问题之在YAML文件中配置了环境变量,但在PHP代码中无法读取到这些环境变量,是什么原因
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
2月前
|
PHP 开发者
【专栏】介绍PHP的命名空间,它是一个用于封装代码、避免名称冲突的机制
【4月更文挑战第27天】本文介绍了PHP的命名空间,它是一个用于封装代码、避免名称冲突的机制。命名空间的作用包括:防止大型项目中的命名冲突,提升代码可读性和可维护性,以及方便代码重用。文章详细阐述了如何定义、导入命名空间,使用完全限定名称以及设置命名空间别名。通过实例展示了命名空间在项目模块划分和第三方库如Laravel中的应用,强调了命名空间在组织和管理PHP代码中的关键作用。
|
12天前
|
安全 PHP 开发者
PHP的开源代码如何影响其安全性?
【7月更文挑战第15天】PHP的开源代码如何影响其安全性?
16 1
|
25天前
|
算法 PHP
【php经典算法】冒泡排序,冒泡排序原理,冒泡排序执行逻辑,执行过程,执行结果 代码
【php经典算法】冒泡排序,冒泡排序原理,冒泡排序执行逻辑,执行过程,执行结果 代码
14 1
|
1月前
|
XML 前端开发 JavaScript
高质量的PHP代码的技巧
高质量的PHP代码的技巧
|
1月前
|
XML 关系型数据库 MySQL
php常用代码分享
php常用代码分享
|
1月前
|
XML 前端开发 API
分享好用便捷的 PHP 代码
21 段实用便捷的 PHP 代码
|
2月前
|
PHP 数据库 开发者
PHP中的异常处理:提升代码稳定性的关键
【5月更文挑战第27天】在软件开发中,异常处理是一种重要的错误管理技术。它允许开发者优雅地处理运行时出现的错误,而不是让程序崩溃。本文将深入探讨PHP中的异常处理机制,包括异常的基本概念,如何抛出和捕获异常,以及如何使用自定义异常类。通过理解和应用这些概念,开发者可以编写出更健壮、更稳定的代码。