ThinkPHP6前后端分离必须彻底禁用模板引擎,否则控制器可能意外渲染HTML干扰JSON输出。需在控制器中设public $view = null,或继承自定义无视图基类。

ThinkPHP6 做前后端分离时,模板引擎必须彻底关闭——不是“不用”,而是从底层禁用,否则控制器可能意外渲染 HTML、干扰 JSON 输出,甚至导致接口返回空白或混合内容。
一、确认并禁用视图层
TP6 默认控制器继承 think\Controller,它会自动初始化视图对象。即使你不调用 fetch() 或 display(),某些中间件或异常处理流程仍可能触发视图渲染。
- 在控制器类顶部明确声明不使用视图:
use think\Controller;class UserController extends Controller { public $view = null; } - 更稳妥的做法是让控制器继承空视图基类(推荐):
新建app/controller/ApiBase.php:<?php declare(strict_types=1); namespace app\controller; use think\Controller; class ApiBase extends Controller { protected $auto_render = false; } - 所有 API 控制器继承
ApiBase,例如:class User extends ApiBase
二、路由配置不走模板逻辑
前端页面由 Nginx/Apache 直接托管 dist 文件,后端只响应 /api/ 开头的请求。路由不能把非 API 请求交给模板控制器处理,否则可能误入视图流程。
- 关闭强制路由:
在config/route.php中设置:'url_route_must' => false - API 路由显式隔离(推荐域名方式):
Route::domain('api', function () { Route::group('v1', function () { Route::get('user', 'api/v1/User/index'); }); }); - 非 API 请求统一 fallback 到前端入口,且排除接口后缀:
Route::rule('[:path]', 'index/index')->ext('html');
加->ext('html')可防止/api/user.json这类请求被错误捕获
三、控制器统一返回 JSON,杜绝隐式输出
TP6 的 return json() 是最安全的输出方式,但需注意两点:不能依赖 $this->success() 等快捷方法,也不能在 return 前有 echo/print_r/var_dump 等输出。
立即学习“PHP免费学习笔记(深入)”;
- 每个控制器方法末尾必须显式写:
return json(['code' => 0, 'data' => $result]); - RESTful 资源控制器(如
Route::resource('users', 'User'))中,index、read、save等方法全部按此规范返回 - 全局异常也需 JSON 化:修改
app/exception.php,让render()方法返回json(['code' => 500, 'msg' => $e->getMessage()])
四、验证是否真正关闭模板引擎
完成配置后,做三步快速验证:
- 访问一个 API 接口(如
/api/v1/user),用 Postman 查看响应头:
应为Content-Type: application/json,且响应体是纯 JSON,无 HTML 标签 - 故意触发一个 404(如请求不存在的
/api/v1/xxx),确认返回的是 JSON 错误(如{"code":404,"msg":"..."}),而非 TP6 默认的 HTML 404 页面 - 在控制器中临时加一行
echo 'test'; return json([...]);,观察是否报错或响应混乱——如有,说明输出缓冲未清理干净,需检查中间件顺序或禁用调试模式
模板引擎关闭不是开关式操作,而是通过控制器基类、路由隔离、返回约定三层协同实现。只要这三点落实到位,TP6 就能稳定作为纯 API 后端运行。



















