当数据库查询出现错误时,比如查询一个不存在的字段,浏览器network的preview不提示任何错误信息的问题
分享
收藏
评论
作者 🐼
heng
-
用的是tp6的版本,该怎么办,这样排查错误很麻烦
在 ThinkPHP 6 中,数据库查询出错时浏览器 Network 的 Preview 看不到错误信息,通常是因为 **全局异常处理器将错误渲染成了 HTML 错误页**,而你的请求可能是 AJAX/JSON 类型,导致 Preview 面板只显示空白的 `<html>` 标签或折叠状态;同时如果开发环境未正确开启调试模式,错误详情也会被系统折叠或隐藏。
下面按优先级提供完整排查与解决步骤:
---
### 🔑 核心解决思路
1. 确保开发环境开启详细调试模式
2. 让异常统一返回 JSON 格式(适配 AJAX/网络请求)
3. 通过 SQL 日志定位具体失败的语句
4. 结合前端控制台验证响应结构
---
### 🛠 逐步解决方案
#### 1️⃣ 开启调试模式(最关键)
检查项目根目录 `.env` 文件:
```ini
APP_DEBUG = true
```
> ✅ 作用:开启后 TP6 会输出完整的异常栈、SQL 语法及详细错误提示。
> ⚠️ 注意:线上部署务必改为 `false`。
#### 2️⃣ 改造全局异常处理器,使 AJAX 请求返回 JSON
TP6 默认对非 AJAX 请求返回 HTML 错误页。打开或新建 `app/exception/Handler.php`:
```php
<?php
namespace app\exception;
use think\exception\Handle;
use think\Response;
use think\Request;
class Handler extends Handle
{
public function render(Request $request, \Throwable $e): Response
{
// 判断是否为 AJAX 或期望 JSON 的请求
$isJsonRequest = $request->isAjax()
|| ($request->header('Accept') && stripos($request->header('Accept'), 'application/json') !== false);
if ($isJsonRequest) {
return json([
'code' => $e->getCode() ? : 500,
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => config('app_debug') ? $this->formatTrace($e) : null,
], 500);
}
// 普通浏览器访问仍返回传统错误页
return parent::render($request, $e);
}
protected function formatTrace(\Throwable $e): array
{
$trace = [];
foreach ($e->getTrace() as $i => $step) {
$trace[$i] = [
'file' => $step['file'] ?? '',
'line' => $step['line'] ?? 0,
'function' => $step['function'] ?? '',
'class' => $step['class'] ?? '',
'type' => $step['type'] ?? '',
'args' => $step['args'] ?? [],
];
}
return ['exception' => $e->getTraceAsString(), 'stack' => $trace];
}
}
```
> ✅ 效果:此时无论查询是否报错,Network 的 Preview 都会直接显示清晰的 JSON 错误对象。
#### 3️⃣ 手动捕获数据库异常(按需)
如果你希望更精细地控制报错逻辑,可在控制器中显式捕获:
```php
use think\facade\Db;
use think\db\exception\DbException;
use think\Exception;
try {
Db::name('users')->field('not_exist_field')->select();
} catch (DbException | Exception $e) {
\think\facade\Log::error('DB Query Failed: ' . $e->getMessage());
// 交由全局异常处理器或手动返回
return json(['code' => 500, 'msg' => '数据表字段不存在或查询异常'], 500);
}
```
#### 4️⃣ 启用 SQL 日志辅助定位
打开 `config/database.php`,确认以下配置:
```php
'debug' => true, // 开启 SQL 调试模式
'sql_log' => true, // 记录执行过的 SQL
'trace' => true, // 在底部显示 SQL 执行列表(HTML模式下)
```
📍 SQL 日志路径:`runtime/log/` 目录下按日期命名的 `.log` 文件,或直接在页面底部的 Debug 面板查看。
#### 5️⃣ 浏览器/前端排查技巧
- 打开 DevTools → Network 面板 → 刷新请求 → 点击该请求
- 查看 `Status` 是否为 `500`(代表后端抛异常)
- `Headers` → `Content-Type` 是否为 `text/html`?若是,说明没走 JSON 响应
- `Preview` / `Response` 两个标签页都点开看看(有时 HTML 被折叠)
- 同时在 `Console` 面板查看是否有前端 JS 拦截或格式解析失败
---
### 💡 附加建议
| 场景 | 推荐做法 |
|------|----------|
| 开发阶段 | 开启 `APP_DEBUG=true` + 自定义 Handler 返回 JSON |
| 生产环境 | 关闭调试,异常仅写日志 `Log::error()`,前端统一提示“系统繁忙” |
| 复杂业务 | 使用 `try...catch` + 事务回滚 + 明确返回码规范 |
| 团队协作 | 统一异常响应格式(如 `{code, message, data}`),避免前端硬编码判断 |
---
按照上述配置后,下次查询不存在字段时,Network 的 Preview 就会直接显示类似:
```json
{
"code": 500,
"message": "Unknown column 'not_exist_field' in 'field list'",
"file": "/app/controller/Index.php",
"line": 42
}
```
排查效率会大幅提升。如遇具体报错堆栈看不清或配置不生效,可提供 `.env` 相关片段和请求方式(同步/异步/路由),我帮你精准定位。