ThinkPHP6 project basic operations (13. Custom exception handling summary error page & API error in some actual combat projects)

Preface

  Generally, routing in a project is divided into return 模板引擎页面and return api接口json数据. The two methods require different content to be returned. If the template engine page encounters an exception, it needs to return an error page. If the api interface encounters an exception, it needs to return json data.
  The development mode and the online mode should return different content. The development mode should return as much specific error information as possible, while the online mode cannot return specific error messages. Generally, it displays a friendly prompt like "Server error, please try again later". Instead of displaying a bunch of error codes (both unfriendly and unsafe).
  If there is a better way, comments are welcome.

1. Anomaly classification

1. The controller cannot be found

When accessing the route, if the controller is wrong, you need to use 空控制器interception to report errors.

2. Method not found

The method cannot be found to modify the BaseController controller in the app directory to override the __call method.

3. The requested resource does not exist

To customize the interception of error messages, you can use Provider to customize the error handling class, override the render method, and return different data according to different errors.

4. System internal exception, HTTP exception, etc.

The third point.

Two, exception handling

1. Pre-processing

(1) The .envfile definition APP_DEBUGdistinguishes between development mode and online mode, true means development mode, false means online mode:

APP_DEBUG = true

(2) app/common.phpDefine the apireturned data format in the file :

function show($status, $message = 'error', $data = [], $httpStatus = 200){
    
    
    $result = [
        "status" => $status,
        "message" => $message,
        "result" => $data
    ];
    return json($result, $httpStatus);
}

(3) Create a new provider.php under the current application and specify a custom exception handling class:

<?php

// 容器Provider定义文件
return [
    'think\exception\Handle' => 'app\\admin\\exception\\Http',
];

(4) To define the status code configuration, you can add the corresponding status code configuration configunder the folder status.php:

<?php

return [
    "success" => 1,
    "error" => 0,

    "http_status" => [
        "not_found" => 404,
        "validate_error" => 422,
        "internal_error" => 500
    ]
];

(5) Prepare error pages (404, 500, etc.)

2. Exception handling detailed code

(1) The controller cannot be found

app/controllerCreate a new Errorclass in the directory ( 文件名固定为Error):

这里需要注意的是,多应用的控制器应该定义在应用文件夹里,这里定义在app目录是为了作用于app下全部应用。

<?php

namespace app\controller;

class Error
{
    
    
    public function __call($name, $arguments)
    {
    
    
        if(request()->isAjax()){
    
    
            return show(config("status.error"), env('app_debug') ? "控制器{
      
      $name}找不到" : '当前请求资源不存在,请稍后再试', [], config("status.http_status.not_found"));
        }else{
    
    
            return view(root_path() . 'public/error/admin/404.html', ['e' => env('app_debug') ? "控制器{
      
      $name}找不到" : '当前请求资源不存在,请稍后再试'], config("status.http_status.not_found"));
        }
    }
}

(2) Method not found

In app/BaseController.phpadding the controller __callmethod:

public function __call($name, $arguments)
    {
    
    
        if(request()->isAjax()){
    
    
            return show(config("status.error"), env('app_debug') ? "找不到{
      
      $name}方法" : '当前请求资源不存在,请稍后再试', [], config("status.http_status.not_found"));
        }else{
    
    
            return view(root_path() . 'public/error/admin/404.html', ['e' => env('app_debug') ? "{
      
      $name}方法找不到" : '当前请求资源不存在,请稍后再试'], config("status.http_status.not_found"));
        }
    }

(3) The requested resource does not exist and the system error is abnormal

app\\admin\\exception\\Http

<?php

namespace app\admin\exception;
use ErrorException;
use Exception;
use InvalidArgumentException;
use ParseError;
use PDOException;
use think\exception\ClassNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\RouteNotFoundException;
use think\Response;
use Throwable;
use TypeError;

class Http extends Handle
{
    
    
    /**
     * Render an exception into an HTTP response.
     *
     * @access public
     * @param \think\Request   $request
     * @param Throwable $e
     * @return Response
     */
    public function render($request, Throwable $e): Response
    {
    
    
        $returnCode = config("status.error");
        $returnMessage = "系统异常,请稍后再试";
        $returnData = [];
        $httpStatus = 500;

        if($e instanceof BusinessException){
    
     // 自定义添加的业务异常
            $returnMessage = $e->getMessage();
            $httpStatus = config("status.http_status.business_error");
        }else if($e instanceof ValidateException){
    
    
            $returnMessage = $e->getError();
            $httpStatus = config("status.http_status.validate_error");
        }else if (($e instanceof ClassNotFoundException || $e instanceof RouteNotFoundException) || ($e instanceof HttpException && $e->getStatusCode() == 404)) {
    
    
            $returnMessage = env('app_debug') ? $e->getMessage() : '当前请求资源不存在,请稍后再试';
            $httpStatus = config("status.http_status.not_found");
        }else if ($e instanceof Exception || $e instanceof PDOException || $e instanceof InvalidArgumentException || $e instanceof ErrorException || $e instanceof ParseError || $e instanceof TypeError || ($e instanceof HttpException && $e->getStatusCode() == 500)) {
    
    
            $returnMessage = env('app_debug') ? $e->getMessage() : '系统异常,请稍后再试';
            $httpStatus = config("status.http_status.internal_error");
        }

        if(request()->isAjax()){
    
    
            return show($returnCode, $returnMessage, $returnData, $httpStatus);
        }else{
    
    
            if($httpStatus == config("status.http_status.not_found")){
    
    
                $errorUrl = 'public/error/admin/404.html';
            }else{
    
    
                $errorUrl = 'public/error/admin/error.html';
            }
            return view(root_path() . $errorUrl, ['e'=>$returnMessage], $httpStatus);
        }

    }
}

The error information returned in the above code eneeds to be displayed on the error page (404, error):

<p class="error-message">{$e ?? ''}</p>

Three, anomaly detection

Anomaly detection points browser 页面访问异常and api接口返回异常also need to check 开发模式and 线上模式.

  1. Controller does not exist
  2. Method does not exist
  3. Actively throw an exception
  4. The system throws an exception

Tips: apiInterface You can use Postmanthe tool simulation, add Headers:
Content-Typeas application/x-www-form-urlencoded
X-Requested-Withisxmlhttprequest

(The bloggers are lazy and won’t post screenshots, but they’ve tested them all, comrades try it out for yourself, let’s post one after all)
Insert picture description here

Guess you like

Origin blog.csdn.net/zy1281539626/article/details/110847728