在 laravel 中处理异常而不在异常处理程序的渲染方法中进行类型检查异常并且不定义自定义异常?

Posted

技术标签:

【中文标题】在 laravel 中处理异常而不在异常处理程序的渲染方法中进行类型检查异常并且不定义自定义异常?【英文标题】:Handle exceptions in laravel without type-checking exceptions in the exception handler's render method and without defining custom exception? 【发布时间】:2020-05-25 19:07:41 【问题描述】:

我正在通过异常处理程序的render方法中的类型检查异常来处理诸如NotFoundHttpExceptionUnauthorizedException之类的laravel异常,赚了很多instanceof 检查在我看来违反了 OCP(对扩展开放,对修改关闭)原则。 该文档通过使用必须从我不想要的控制器(或任何地方)抛出的可渲染异常(https://laravel.com/docs/6.x/errors#renderable-exceptions)解决了这个问题,我想捕获 laravel 异常,例如 ModelNotFoundException处理程序类并以干净的方式返回我的自定义响应,换句话说,我正在寻找一种干净的方式来处理 laravel 异常而不从控制器抛出异常。

【问题讨论】:

该框架为您提供了两种处理异常的方法,您似乎都不满意。为什么需要这种级别的微调控制?如果您只是想在发生给定异常时更改页面上显示的内容,您可以通过创建自己的文件来覆盖刀片文件,例如resources/views/errors/404.blade.php。或者您是否还有其他需要实现的条件逻辑? 【参考方案1】:

如果只是关于 OCP,你可以使用责任链设计模式,你可以创建一个类(它是 open-for-extension closed-for-modifications),它有一个“next”字段,它是来自相同的类类型,并进行您想要的转换:

interface ErrorHandler 
    function handleError($request);


abstract class NodeInErrorHandlerChain 
    private $next; // It should have the same `NodeInErrorHandlerChain` type

    public NodeInErrorHandlerChain($next) 
        $this->next = $next;
    

    abstract protected function currentHandler($exception, $request);

    public function handle($exception, $request) 
        $current = currentHandler($exception, $request);
        return $current != null ? $current : 
              ($next == null ? null : $next->handle($exception, $request));
    

然后实现如下:

class ModelNotFoundNode extends NodeInErrorHandlerChain 
    protected function currentHandler($exception, $request) 
        if($exception instanceof ModelNotFoundException) 
            return ModelNotFoundHandler($request); // This should be easy to implement
        
    

所以,现在你只检查ModelNotFoundException,如果你想检查其他类型,创建ModelNotFoundNode$next不等于null,而是等于例如ValidationException(你可以实现以相同的方式),因此添加任何其他例外只会创建另一个扩展NodeInErrorHandlerChain的类,并在创建链时将$next设置为链的前一个最后一个元素(例如在在您的应用中提供依赖注入的 Provider)。

    $this->app->singleton(NodeInErrorHandlerChain::class, function ($app) 
        return new ModelNotFoundNode(ValidationExceptionNode(null));
    );

【讨论】:

好的,我会试试这个。谢谢

以上是关于在 laravel 中处理异常而不在异常处理程序的渲染方法中进行类型检查异常并且不定义自定义异常?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5.1 中的异常处理器和HTTP异常处理 abort()

处理来自 PHPUnit (Laravel 5.2) 的自定义异常

Laravel系列7.2错误与异常处理

CSRF 令牌在带有 Ajax 请求的 Laravel 5.1 异常处理程序中不起作用

9.5 异常处理规则

Laravel 中的异常处理