搜索

PHP Master | Exceptional Exceptions

核心要点

  • PHP 异常是一种特殊的类,可以抛出和捕获,表示意外事件。与不可恢复的错误不同,异常旨在由调用代码处理,并沿执行链向上冒泡,直到被捕获。
  • PHP 错误和异常的区别在于:错误是不可恢复的,发生在主执行循环中,表示代码或环境稳定性存在问题;而异常是可恢复的,可能发生在主执行循环之外,并且不表示系统不稳定。
  • 不是所有非成功的情况都需要抛出异常。只有在确实无法继续执行时才应抛出异常。这意味着一个不属于普通操作或标准的动作,一个异常,与正常和预期情况有所偏差。
  • 抛出一般的 Exception 等同于说存在“问题”,而代码无法知道发生了什么。相反,应始终抛出自定义异常,以告知调用代码当前情况,从而对发生的情况进行细粒度控制。
  • 全局捕获块是最高级别的捕获块,必须捕获所有冒泡到该级别的异常。它应该是生产代码中唯一的一般异常处理程序。其他处理程序必须是特定的,并且仅限于它知道如何处理和负责的异常。

PHP 5 引入了异常处理机制,这是一种特殊的类,可以抛出和捕获(与引发的错误相反),表示意外事件。与错误不同,异常旨在由调用代码处理,并沿执行链向上冒泡,直到被捕获。一旦抛出异常,当前作用域中的代码将停止执行(因此,throw 语句之后的任何行都不会执行),控制权将返回到第一个匹配的异常处理程序(捕获块、配置的异常处理程序或语言提供的异常处理程序)。只有当异常被捕获时,代码执行才会从那里继续。本文并非旨在从入门级别讲解异常,而是就如何更好地使用异常提供一些建议。如果您以前从未使用过异常,您可能需要查阅 PHP 手册,或阅读我的朋友们编写的《PHP Master:编写尖端代码》一书,该书出色地讲解了编写现代、合理的 PHP 代码所需的一切知识。

错误并非异常

您可能已经了解了异常,但您可能想知道 PHP 错误和(自定义)异常之间的区别。逻辑实际上很简单:错误是不可恢复的,发生在主执行循环中,并且表示环境的稳定性。例如,如果您尝试将标量值作为数组访问而引发了 E_NOTICE,则表示您的代码存在问题。无法保证继续执行是安全的。无法在执行期间纠正该条件。如果由于解析器发现意外的 T_IF 而引发了 E_PARSE,那么您就会明白这如何影响事物的稳定性。另一方面,异常是可恢复的,可以(并且通常会)发生在主执行循环之外,并且不会指示系统的稳定性。它是一个组件说:“我无法使用给定的输入完成您的请求,因此您可以随意处理该信息。”如果库抛出 LengthException,则表示传递的值过长或过短,因此它无法使用当前值完成给定的指令。这并不意味着您的环境不稳定,只是意味着您的代码必须通过填充或截断来调整值的长度。您的代码可以捕获此异常,更新值,然后重试。

并非所有异常都是例外情况

这是最难回答的问题之一:究竟什么情况需要抛出异常?当然,您的异常必须符合上一段中的三个规则。当遇到损坏的内存时抛出异常是非常糟糕的做法。您的代码应该改为引发错误,以便 PHP 能够尽快中止,因为事实证明,环境不安全以继续执行。但是,即使错误是不必要的,也不是所有非成功的情况都需要异常。也就是说:并非所有不成功的情况都是例外情况。“异常”这个词指的是不属于普通操作或标准的动作,一个异常,与正常和预期情况有所偏差。一位前同事曾经在晚餐时告诉我他们公司使用的 XML/RPC 服务的设计情况,该服务是所有面向公众的操作的支柱。架构师随后了解了异常以及它们在指示非成功状态方面的便利性。该支柱除了其他功能外,还提供了单点登录功能。Web 应用程序不会直接访问数据库,而是查询 XML/RPC 服务,然后该服务将根据为所有 Web 应用程序提供服务的集中式数据存储进行回复。当提供有效的凭据时,将返回成功状态。当出现问题时,将抛出异常,并显示一条消息,指示失败的原因。易于捕获,您可以以醒目的、闪亮的错误消息向用户显示该消息。但是,用户提供不正确的用户名和/或密码真的偏离了预期吗?在我的项目中,我处理的用户并不完美,他们会打错字或忘记事情。获取不正确的凭据是非常常见的,甚至比有效的凭据更常见。验证凭据是登录系统的预期行为,因此在这种情况下,XML/RPC 服务应返回一个状态,指示验证的成功与否。尽管凭据未通过,但验证过程本身仍然成功执行。如果验证过程未正确执行,则说明还有其他问题。也许数据存储不可访问,或者其他什么原因。登录系统无法连接到其数据存储的情况非常不常见,因为它无法在没有数据存储的情况下运行。因此,这需要抛出异常。注意:有些人可能会争辩说,登录系统无法连接到数据存储是环境不稳定的标志,因此应该引发错误。但是,登录系统不负责为数据存储引发错误。相反,如果数据存储连接器/包装器认为有必要,则应引发错误。一般来说,您可以将异常视为开发人员必须介入、查看情况并进行处理的情况。发生异常场景的代码本身无法做到这一点。这可能是开发人员已经查看过代码,并且他们处理它的方式是在它发生时让它发生。不要开始将所有异常都通过邮件发送给网络运营中心;他们不会感激的!处理您可以并且应该处理的内容,并且只有在确实无法继续执行时才抛出异常。

“问题”

几年前,当我徒步旅行穿过欧洲时,我在希腊的一个火车站偶然发现了一个令人难忘的景象。其中一个储物柜区域看起来像炸弹爆炸了一样,门散落在地上,一半挂在铰链上,或者被砸碎了。我后来了解到他们正在拆除储物柜区域,但值得注意的是,他们是如何向客户传达此区域已停用的。在中央部分贴了很多胶带,上面贴着一张纸,上面写着“问题”两个字。从技术上讲,这是完全正确的。储物柜显然出了问题,并且情况已通过向客户传达来处理。您可能会觉得它很有趣,但实际上您在代码中经常会看到这种情况。如果您只抛出 Exception,那么您基本上就是在说“问题”,而代码无法知道发生了什么。虽然 Exception 是每个异常的基类,但您可以使用您自己的类型扩展它。在 SPL 库中可以找到更广泛的异常集合,但这远非极限。查看 Zend Framework 或 Symfony 等主要的 PHP 框架,您会发现它们几乎为每种不同的情况都使用自定义异常。编写所有这些文件以便可以动态加载它们并维护所有不同类型有点麻烦,但这为框架和该框架的使用者提供了对发生情况的细粒度控制。如果只抛出 Exception,那么您只能确定某些事情不对劲,您不妨放弃。这意味着您使用异常的方式就像它们是错误一样,将捕获块用作静默操作符,并且只是放弃了有人可以以某种方式纠正这种情况的希望。

全局捕获

如果使用非自定义异常和捕获所有可能的异常是一个坏主意,那么为什么语言甚至允许这样做呢?始终使用和捕获特定异常的规则有一个例外,那就是全局捕获规则。全局捕获块是最高级别的捕获块,必须捕获所有冒泡到该级别的异常。PHP 本身包含一个(您是否见过“致命错误:未捕获的异常在……”消息?),但您可以使用自定义处理程序覆盖它以作为后备。您可以使用 set_exception_handler() 函数设置此处理程序,因此您可以随意这样做,然后向您的 PHPMD 规则集中添加一条规则,禁止类似于“catch (Exception $e) {”之类的行。这是唯一一个应该在生产代码中找到的一般异常处理程序的原因,它捕获尚未捕获的 Exception 类的每个实例。其他处理程序必须是特定的,并且仅限于它知道如何处理和负责的异常。在这里谨慎行事,让一个可处理的异常冒泡一次(然后在代码中修复它)肯定比捕获太多并充当静默操作符要好得多。

总结

总而言之,只有当您的代码无法使用给定的输入完成请求的指令时才抛出异常,始终抛出自定义异常,该异常实际上会告诉调用代码当前情况,并且如果您调用其他代码,则只捕获您可以并且应该处理的异常。这将使您的组件更少像黑盒(自定义异常),并减少集成您的组件的开发人员必须更改您的代码的可能性(不要捕获您不应该捕获的异常)。我们总是告诉我们的客户/管理人员要具体,但我们也应该具体!

(图片来自 Fotolia)

关于 PHP 异常处理的常见问题

  • PHP 异常处理的目的是什么?

PHP 异常处理是一种强大的机制,允许开发人员管理程序执行期间可能发生的错误和异常情况。它提供了一种将控制从程序的一个部分转移到另一个部分的方法。PHP 异常处理用于在发生指定错误时更改代码执行的正常流程。这可以使代码更易于阅读和管理,因为它将错误处理代码与主程序逻辑分开。

  • PHP 中的 try-catch 块是如何工作的?

在 PHP 中,try-catch 块用于处理异常。try 块包含可能抛出异常的代码,而 catch 块包含如果 try 块中抛出异常将执行的代码。如果 try 块中抛出异常,则脚本停止运行,控制权将传递给与抛出的异常类型匹配的第一个 catch 块。

  • finally 块在 PHP 异常处理中的作用是什么?

PHP 异常处理中的 finally 块用于确保始终执行一段代码,无论是否抛出异常。这对于清理活动(例如关闭文件或数据库连接)非常有用,无论操作成功还是失败都应执行这些活动。

  • 如何在 PHP 中创建自定义异常?

在 PHP 中,您可以通过扩展内置的 Exception 类来创建自定义异常。这允许您向异常添加自定义功能,或创建特定于应用程序域的异常。要创建自定义异常,您可以定义一个扩展 Exception 的新类,然后添加所需的任何自定义方法或属性。

  • PHP 中异常和错误有什么区别?

在 PHP 中,错误是一个严重的问题,会阻止脚本运行,而异常是一个改变正常执行流程的条件。错误通常是由语法错误或调用未定义函数等原因引起的。另一方面,异常通常用于处理对程序并非致命但需要特殊处理的条件。

  • 如何在 PHP 中处理多个异常?

在 PHP 中,您可以使用多个 catch 块来处理多个异常。每个 catch 块处理特定类型的异常。当抛出异常时,将按代码中出现的顺序检查 catch 块。将执行第一个能够处理抛出的异常类型的 catch 块。

  • 我可以在 PHP 中重新抛出异常吗?

是的,您可以在 PHP 中重新抛出异常。如果您想以某种方式处理异常,但又想让更高级别的异常处理程序捕获它,这将非常有用。要重新抛出异常,只需在 catch 块中使用 throw 语句即可。

  • 如何在 PHP 中记录异常?

在 PHP 中,您可以通过在 catch 块中使用 error_log 函数来记录异常。这允许您将有关异常的信息(包括其消息和堆栈跟踪)记录到指定的日志文件中。

  • PHP 中的 PDOException 是什么?

PDOException 是一种异常,当 PDO 操作中发生错误时会抛出该异常。PDO(PHP 数据对象)是一个数据库抽象层,它为访问 PHP 中的数据库提供一致的接口。PDOException 提供有关错误的信息,包括 SQLSTATE 错误代码和数据库驱动程序的错误消息。

  • 如何在 PHP 中处理未捕获的异常?

在 PHP 中,您可以通过定义自定义异常处理程序函数,然后使用 set_exception_handler 函数将其设置为默认异常处理程序来处理未捕获的异常。每当抛出未被 try-catch 块捕获的异常时,都会调用此函数。

以上是PHP主|例外的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
使用数据库存储会话的优点是什么?使用数据库存储会话的优点是什么?Apr 24, 2025 am 12:16 AM

使用数据库存储会话的主要优势包括持久性、可扩展性和安全性。1.持久性:即使服务器重启,会话数据也能保持不变。2.可扩展性:适用于分布式系统,确保会话数据在多服务器间同步。3.安全性:数据库提供加密存储,保护敏感信息。

您如何在PHP中实现自定义会话处理?您如何在PHP中实现自定义会话处理?Apr 24, 2025 am 12:16 AM

在PHP中实现自定义会话处理可以通过实现SessionHandlerInterface接口来完成。具体步骤包括:1)创建实现SessionHandlerInterface的类,如CustomSessionHandler;2)重写接口中的方法(如open,close,read,write,destroy,gc)来定义会话数据的生命周期和存储方式;3)在PHP脚本中注册自定义会话处理器并启动会话。这样可以将数据存储在MySQL、Redis等介质中,提升性能、安全性和可扩展性。

什么是会话ID?什么是会话ID?Apr 24, 2025 am 12:13 AM

SessionID是网络应用程序中用来跟踪用户会话状态的机制。1.它是一个随机生成的字符串,用于在用户与服务器之间的多次交互中保持用户的身份信息。2.服务器生成并通过cookie或URL参数发送给客户端,帮助在用户的多次请求中识别和关联这些请求。3.生成通常使用随机算法保证唯一性和不可预测性。4.在实际开发中,可以使用内存数据库如Redis来存储session数据,提升性能和安全性。

您如何在无状态环境(例如API)中处理会议?您如何在无状态环境(例如API)中处理会议?Apr 24, 2025 am 12:12 AM

在无状态环境如API中管理会话可以通过使用JWT或cookies来实现。1.JWT适合无状态和可扩展性,但大数据时体积大。2.Cookies更传统且易实现,但需谨慎配置以确保安全性。

您如何防止与会议有关的跨站点脚本(XSS)攻击?您如何防止与会议有关的跨站点脚本(XSS)攻击?Apr 23, 2025 am 12:16 AM

要保护应用免受与会话相关的XSS攻击,需采取以下措施:1.设置HttpOnly和Secure标志保护会话cookie。2.对所有用户输入进行输出编码。3.实施内容安全策略(CSP)限制脚本来源。通过这些策略,可以有效防护会话相关的XSS攻击,确保用户数据安全。

您如何优化PHP会话性能?您如何优化PHP会话性能?Apr 23, 2025 am 12:13 AM

优化PHP会话性能的方法包括:1.延迟会话启动,2.使用数据库存储会话,3.压缩会话数据,4.管理会话生命周期,5.实现会话共享。这些策略能显着提升应用在高并发环境下的效率。

什么是session.gc_maxlifetime配置设置?什么是session.gc_maxlifetime配置设置?Apr 23, 2025 am 12:10 AM

thesession.gc_maxlifetimesettinginphpdeterminesthelifespanofsessiondata,setInSeconds.1)它'sconfiguredinphp.iniorviaini_set().2)abalanceIsiseededeedeedeedeedeedeedto to to avoidperformance andununununununexpectedLogOgouts.3)

您如何在PHP中配置会话名?您如何在PHP中配置会话名?Apr 23, 2025 am 12:08 AM

在PHP中,可以使用session_name()函数配置会话名称。具体步骤如下:1.使用session_name()函数设置会话名称,例如session_name("my_session")。2.在设置会话名称后,调用session_start()启动会话。配置会话名称可以避免多应用间的会话数据冲突,并增强安全性,但需注意会话名称的唯一性、安全性、长度和设置时机。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。