swoft 学习笔记之异常处理

异常处理包含定义异常类和与之对应的异常处理类,处理类通常包含名字为 handle 的方法

一、定义异常类

<?php

namespace App\Exception;

Class ApiException extends \Exception {

}

二、定义异常处理类

<?php

namespace App\Exception\Handler;

use App\Exception\ApiException;
use Swoft\Error\Annotation\Mapping\ExceptionHandler;
use Swoft\Http\Message\Response;
use Swoft\Http\Server\Exception\Handler\AbstractHttpErrorHandler;

/**
 * @ExceptionHandler(ApiException::class)
 */
class ApiExceptionHandler extends AbstractHttpErrorHandler
{
    /**
     * @param \Throwable $e
     * @param Response $response
     * @return Response
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     */
    public function handle(\Throwable $e, Response $response): Response
    {
        $data = [
            'code'  => -1,
            'msg'   => $e->getMessage()
        ];
        return $response->withData($data);
    }
}

三、HTTP异常接管

当在做 API 开发的时候,后端第一个要做的就是验证参数的合法性。当参数不合法时,会返回给客户端具体错误信息,此时是通过抛出异常的方式。因此我在系统自带的异常处理类里面稍微做了些修改。具体修改思路是:如果抛出的异常时验证类的异常,则直接返回给客户端错误信息,如果不是的话,再判断当前环境是开发调试还是生产,如果是调试生产,则抛出具体错误信息,方便调试,如果是生产环境,则没必要把详细的错误信息返回给客户端,因为客户端根本不关心具体错在哪了,此时需要统一返回服务端内部错误就行,并视情况而定,到底是否需要记录日志。

<?php declare(strict_types=1);

namespace App\Exception\Handler;

use const APP_DEBUG;
use function get_class;
use ReflectionException;
use function sprintf;
use Swoft\Bean\Exception\ContainerException;
use Swoft\Error\Annotation\Mapping\ExceptionHandler;
use Swoft\Http\Message\Response;
use Swoft\Http\Server\Exception\Handler\AbstractHttpErrorHandler;
use Swoft\Log\Helper\CLog;
use Throwable;
use App\Model\Struct\DataStruct;
use App\Model\Struct\ConstantStruct;
use Swoft\Validator\Exception\ValidatorException;

/**
 * Class HttpExceptionHandler
 *
 * @ExceptionHandler(\Throwable::class)
 */
class HttpExceptionHandler extends AbstractHttpErrorHandler
{
    /**
     * @param Throwable $e
     * @param Response $response
     *
     * @return Response
     * @throws ReflectionException
     * @throws ContainerException
     */
    public function handle(Throwable $e, Response $response): Response
    {
        // Log
        CLog::error($e->getMessage());

        //如果是验证类异常,则返回给客户端,不需要记录日志
        if( $e instanceof ValidatorException ){
            $data = [
                'code' => ConstantStruct::VALIDATOR_ERROR,
                'msg'  => $e->getMessage(),
            ];

            return $response->withData($data);
        }

        //如果是系统内部异常,则判断是否是环境测试还是生产
        //如果是非 debug 模式,则统一抛出系统内部错误
        if ( ! APP_DEBUG ) {

            $data = [
                'code' => ConstantStruct::CODE_ERROR,
                'msg'  => $e->getMessage(),
            ];

            return $response->withData($data);
        }

        //如果是 debug 模式,就抛出具体错误信息,便于调试
        $data = [
            'code'  => $e->getCode(),
            'error' => sprintf('(%s) %s', get_class($e), $e->getMessage()),
            'file'  => sprintf('At %s line %d', $e->getFile(), $e->getLine()),
            'trace' => $e->getTraceAsString(),
        ];
        return $response->withData($data);
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
今年不学习,明天惨唧唧。
zs4336
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!