Resumo do tratamento de exceções personalizadas na página de erro do projeto e erro de API
Prefácio
Geralmente, o roteamento em um projeto é dividido em retorno 模板引擎页面
e retorno api接口json数据
. Os dois métodos exigem o retorno de conteúdo diferente. Se a página do mecanismo de modelo encontrar uma exceção, ela precisará retornar uma página de erro. Se a interface api encontrar uma exceção, ela precisará retornar dados json.
O modo de desenvolvimento e o modo online devem retornar conteúdo diferente. O modo de desenvolvimento deve retornar o máximo possível de informações de erro específicas, enquanto o modo online não pode retornar mensagens de erro específicas. Geralmente, ele exibe um prompt amigável como "Erro do servidor, tente novamente mais tarde". Em vez de exibir um monte de códigos de erro (hostis e inseguros).
Se houver uma maneira melhor, comentários são bem-vindos.
1. Classificação de anomalias
1. O controlador não pode ser encontrado
Ao acessar a rota, se o controlador estiver errado, você precisa usar a 空控制器
interceptação para relatar os erros.
2. Método não encontrado
O método não pode ser encontrado para modificar o controlador BaseController no diretório do aplicativo para substituir o método __call.
3. O recurso solicitado não existe
Para personalizar a interceptação de mensagens de erro, você pode usar o Provedor para personalizar a classe de tratamento de erros, substituir o método de renderização e retornar dados diferentes de acordo com erros diferentes.
4. Exceção interna do sistema, exceção HTTP, etc.
O terceiro ponto.
Dois, tratamento de exceção
1. Pré-processamento
(1) A
.env
definição do arquivoAPP_DEBUG
distingue entre o modo de desenvolvimento e o modo online, verdadeiro significa modo de desenvolvimento, falso significa modo online:
APP_DEBUG = true
(2)
app/common.php
Defina oapi
formato dos dados retornados no arquivo :
function show($status, $message = 'error', $data = [], $httpStatus = 200){
$result = [
"status" => $status,
"message" => $message,
"result" => $data
];
return json($result, $httpStatus);
}
(3) Crie um novo provider.php no aplicativo atual e especifique uma classe de tratamento de exceção personalizada:
<?php
// 容器Provider定义文件
return [
'think\exception\Handle' => 'app\\admin\\exception\\Http',
];
(4) Defina a configuração do código de status, você pode adicionar a configuração do código de status correspondente
config
na pastastatus.php
:
<?php
return [
"success" => 1,
"error" => 0,
"http_status" => [
"not_found" => 404,
"validate_error" => 422,
"internal_error" => 500
]
];
(5) Prepare as páginas de erro (404, 500, etc.)
2. Código detalhado de manipulação de exceção
(1) O controlador não pode ser encontrado
app/controller
Crie uma nova Error
classe no diretório ( 文件名固定为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) Método não encontrado
Ao app/BaseController.php
adicionar o __call
método do controlador :
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) O recurso solicitado não existe e o erro do sistema é anormal
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);
}
}
}
A mensagem de erro retornada no código acima e
precisa ser exibida na página de erro (404, erro):
<p class="error-message">{$e ?? ''}</p>
Três, detecção de anomalias
A detecção de anomalia aponta o navegador 页面访问异常
e api接口返回异常
também precisa verificar 开发模式
e 线上模式
.
- Controlador não existe
- Método não existe
- Lance ativamente uma exceção
- O sistema lança uma exceção
Dicas:
api
Interface Você pode usarPostman
a simulação de ferramenta, adicioneHeaders
:
Content-Type
comoapplication/x-www-form-urlencoded
X-Requested-With
estáxmlhttprequest
(Os blogueiros são preguiçosos e não postam capturas de tela, mas eles testaram todos, camaradas experimentem você mesmo, vamos postar um afinal)