首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

完善你的Laravel异常处理

异常处理是编程中十分重要但也最容易被人忽视的语言特性,它为开发者提供了处理程序运行时错误的机制,对于程序设计来说正确的异常处理能够防止泄露程序自身细节给用户,给开发者提供完整的错误回溯堆栈,同时也能提高程序的健壮性。

这篇文章我们来简单梳理一下Laravel中提供的异常处理能力,然后讲一些在开发中使用异常处理的实践,如何使用自定义异常、如何扩展Laravel的异常处理能力。

注册异常Handler

这里又要回到我们说过很多次的Kernel处理请求前的bootstrap阶段,在bootstrap阶段的 部分中Laravel设置了系统异常处理行为并注册了全局的异常处理器:

将 的 方法注册为程序的全局处理器方法:

在处理器里主要通过 的 方法上报异常、这里是记录异常到 文件中,然后根据请求类型渲染异常的响应生成输出给到客户端。这里的ExceptionHandler就是 类的实例,它是在项目最开始注册到服务容器中的:

这里再顺便说一下 函数,它的作用是注册错误处理器函数,因为在一些年代久远的代码或者类库中大多是采用PHP那件函数 函数来抛出错误的,异常处理器只能处理Exception不能处理Error,所以为了能够兼容老类库通常都会使用 注册全局的错误处理器方法,在方法中捕获到错误后将错误转化成异常再重新抛出,这样项目中所有的代码没有被正确执行时都能抛出异常实例了。

常用的Laravel异常实例

中针对常见的程序异常情况抛出了相应的异常实例,这让开发者能够捕获这些运行时异常并根据自己的需要来做后续处理(比如:在catch中调用另外一个补救方法、记录异常到日志文件、发送报警邮件、短信)

在这里我列一些开发中常遇到异常,并说明他们是在什么情况下被抛出的,平时编码中一定要注意在程序里捕获这些异常做好异常处理才能让程序更健壮。

Laravel中执行SQL语句发生错误时会抛出此异常,它也是使用率最高的异常,用来捕获SQL执行错误,比方执行Update语句时很多人喜欢判断SQL执行后判断被修改的行数来判断UPDATE是否成功,但有的情景里执行的UPDATE语句并没有修改记录值,这种情况就没法通过被修改函数来判断UPDATE是否成功了,另外在事务执行中如果捕获到QueryException 可以在catch代码块中回滚事务。

通过模型的 和 方法获取单条记录时如果没有找到会抛出这个异常( 和 找不到数据时会返回NULL)。

请求未通过Laravel的FormValidator验证时会抛出此异常。

用户请求未通过Laravel的策略(Policy)验证时抛出此异常

请求路由时HTTP Method不正确

Laravel的处理HTTP请求不成功时抛出此异常

扩展Laravel的异常处理器

上面说了Laravel把 注册成功了全局的异常处理器,代码中没有被 到的异常,最后都会被 捕获到,处理器先上报异常记录到日志文件里然后渲染异常响应再发送响应给客户端。但是自带的异常处理器的方法并不好用,很多时候我们想把异常上报到邮件或者是错误日志系统中,下面的例子是将异常上报到Sentry系统中,Sentry是一个错误收集服务非常好用:

还有默认的渲染方法在表单验证时生成响应的JSON格式往往跟我们项目里统一的 格式不一样这就需要我们自定义渲染方法的行为。

自定义后,在请求未通过 验证时会抛出 , 之后异常处理器捕获到异常后会把错误提示格式化为项目统一的JSON响应格式并输出给客户端。这样在我们的控制器中就完全省略了判断表单验证是否通过如果不通过再输出错误响应给客户端的逻辑了,将这部分逻辑交给了统一的异常处理器来执行能让控制器方法瘦身不少。

使用自定义异常

这部分内容其实不是针对 框架自定义异常,在任何项目中都可以应用我这里说的自定义异常。

我见过很多人在 或者 类的方法中会根据不同错误返回不同的数组,里面包含着响应的错误码和错误信息,这么做当然是可以满足开发需求的,但是并不能记录发生异常时的应用的运行时上下文,发生错误时没办法记录到上下文信息就非常不利于开发者进行问题定位。

下面的是一个自定义的异常类

定义完异常类我们就能在代码逻辑中抛出异常实例了

除了上面 列出的情况更多的时候我们是在捕获到上面列举的通用异常后在 代码块中抛出与业务相关的更细化的异常实例方便开发者定位问题,我们将上面的 按照这种策略修改一下

在上面定义 类的时候第四个参数 是一个实现了 接口类实例,在这种情景下我们因为捕获到了 的异常实例而抛出了 的实例,然后通过这个参数将 实例传递给 异常的堆栈,这提供给我们回溯整个异常的能力来获取更多上下文信息,而不是仅仅只是当前抛出的异常实例的上下文信息, 在错误收集系统可以使用类似下面的代码来获取所有异常的信息。

异常处理是 非常重要但又容易让开发者忽略的功能,这篇文章简单解释了 内部异常处理的机制以及扩展 异常处理的方式方法。更多的篇幅着重分享了一些异常处理的编程实践,这些正是我希望每个读者都能看明白并实践下去的一些编程习惯,包括之前分享的 的应用也是一样。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190207G0BK8300?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券