Laravel 异常处理程序

问题描述 投票:0回答:3

我正在使用 Laravel 开发一个项目,在渲染函数内的

Exceptions\Handler.php
中捕获了异常,如下所示:

public function render($request, Exception $e){
      switch(get_class($e)){
              case SOME_EXCEPTION::class:
                    do something..
              ...
              ...
              default:
                    do something..
     }

如您所见,问题是在很多情况下代码变得丑陋且混乱

如何解决这个问题?

php laravel exception laravel-5.1
3个回答
0
投票

如果您的自定义异常扩展了一个公共接口,您可以只检查该接口,然后调用合约方法。

if ($e instanceof CustomExceptionInterface) {
    return $e->contractMethod();
}

0
投票

好的,找到了让它看起来更好的方法。 如果有人想改进 Laravel 中的异常处理程序,请遵循以下步骤:

在 app/providers 下创建新的服务提供者,我们将其命名为 ExceptionServiceProvider.php

    class ExceptionServiceProvider extends ServiceProvider {

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(ExceptionFactory::class);
    }

    public function boot(ExceptionFactory $factory){
        $factory->addException(UnauthorizedException::class, JsonResponse::HTTP_NOT_ACCEPTABLE);
        $factory->addException(ConditionException::class, JsonResponse::HTTP_NOT_ACCEPTABLE, "Some Fixed Error Message");

    }
}

在项目中的某个位置创建

ExceptionFactory
类,其中包含
addException()
方法以及代码和消息的 getter

class ExceptionFactory{


private $exceptionsMap = [];
private $selectedException;

public function addException($exception, $code, $customMessage = null) {
    $this->exceptionsMap[$exception] = [$code, $customMessage];
}

public function getException($exception){
    if(isset($this->exceptionsMap[$exception])){
        return $this->exceptionsMap[$exception];
    }
    return null;
}

public function setException($exception){
    $this->selectedException = $exception;
}

public function getCode(){
    return $this->selectedException[0];
}

public function getCustomMessage(){
    return $this->selectedException[1];
}

}

然后剩下要做的就是在

Exceptions/handler.php
内 在渲染函数中:

private $exceptionFactory;

    public function __construct(LoggerInterface $log, ExceptionFactory $exceptionFactory){
        parent::__construct($log);
        $this->exceptionFactory = $exceptionFactory;
    }

public function render($request, Exception $e){
        $error = new \stdClass();
        $customException = $this->exceptionFactory->getException(get_class($e));

        if(isset($customException)){
            $this->exceptionFactory->setException($customException);
            $error->code = $this->exceptionFactory->getCode();
            $error->message = $e->getMessage();
            $customMessage = $this->exceptionFactory->getCustomMessage();
            if(isset($customMessage)){
                $error->message = $customMessage;
            }
       }
       return new JsonResponse($error, $error->code);
 }
}

最后要记住的是将

ServiceProvider
放在应用程序设置中的
config/app.php
下,只需添加:

\App\Providers\ExceptionServiceProvider::class

我希望你会像我一样发现这很有用。


0
投票
这是封面
  • 网页
  • API
  • 日志查看器
  • 包异常处理程序
<?php

namespace App\Exceptions;
use Throwable;

use Illuminate\Support\Str;
use App\Traits\ApiResponser;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\Exceptions\HttpResponseException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Illuminate\Http\Exceptions\ThrottleRequestsException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Saifur\FileManager\app\Facades\Helpers\SFMCommonFacade;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;

class Handler extends ExceptionHandler
{
    use ApiResponser;
    /**
     * A list of the exception types that are not reported.
     *
     * @var array<int, class-string<Throwable>>
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array<int, string>
     */
    protected $dontFlash = [
        'current_password',
        'password',
        'password_confirmation',
    ];

    /**
     * Register the exception handling callbacks for the application.
     *
     * @return void
     */
    public function register()
    {
        $this->reportable(function (Throwable $e) {
            //
        });
    }

    public function report(Throwable $exception)
    {
        parent::report($exception);
    }

    protected function unauthenticated($request, AuthenticationException $exception)
    {
        return $this->set_response(null,401,'error',['Unauthenticated.']);
    }


    public function render($request, Throwable $e)
    {
        if (\config('app.debug'))  // debug mode => true error details is displayed
        {
            if (Str::startsWith(request()->getRequestUri(), '/log-viewer')) // for web + log viewer + debug mode route handler
            {
                return redirect('log-viewer/login');
            }
            return parent::render($request, $e);  // for web(except: /log-viewer) + api + debug mode route handler
        }

        // Processing the status code, exception ($e)
        $status = Response::HTTP_INTERNAL_SERVER_ERROR;

        [$status, $e, $message] = SFMCommonFacade::sfm_custom_exceptions($e);  // Saifur Package Exceptions

        if ($e instanceof HttpResponseException)
        {
            $status = Response::HTTP_INTERNAL_SERVER_ERROR;
        }
        elseif ($e instanceof MethodNotAllowedHttpException)
        {
            $status = Response::HTTP_METHOD_NOT_ALLOWED;
            $e = new MethodNotAllowedHttpException([], ('Method not allowed!'), $e);
        }
        elseif ($e instanceof NotFoundHttpException)
        {
            $status = Response::HTTP_NOT_FOUND;
            $e = new NotFoundHttpException(('Not found!'));
        }
        elseif ($e instanceof AuthorizationException)
        {
            $status = Response::HTTP_FORBIDDEN;
            $e = new AuthorizationException(('Forbidden request! You do not have the required permission to access.'), $status);
        }
        elseif ($e instanceof \Dotenv\Exception\ValidationException && $e->getResponse())
        {
            $status = Response::HTTP_BAD_REQUEST;
            $e = new \Dotenv\Exception\ValidationException(('Bad Request!'), $status, $e);
        }
        elseif ($e instanceof AuthenticationException)
        {
            $status = 401;
            $e = new HttpException($status, 'Unauthenticated!');
        }
        elseif ($e instanceof ThrottleRequestsException)
        {
            $retry_after = $e->getHeaders()['Retry-After'] ?? 0;
            $status = 429;
            $e = new HttpException($status, 'Too many requests! Try after '.$retry_after.' seconds!');
        }
        // Handle OAuth2 Server Exception
        elseif ($e instanceof OAuthServerException) {
            // Customize the error message based on the exception's properties
            $message = 'Access Denied: ' . $e->getMessage();
            $status = 403;
            $e = new HttpException($status, $message);
        }
        elseif ($e)
        {
            $e = new HttpException($status, $message ?? 'Internal Server Error!');
        }

        // Finally return the response
        if (Str::startsWith(request()->getRequestUri(), '/log-viewer') && $status == 401) // for web + log viewer route handler
        {
            return redirect('log-viewer/login');
        }
        else if (Str::startsWith(request()->getRequestUri(), '/api')) // for api route handler
        {
            return $this->set_response(null, $status, 'error', [$e->getMessage()]);
        }
        else{  // for web route handler
            return parent::render($request, $e);
        }
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.