ThinkPHP前后端分离需绕开模板渲染、Session依赖和默认路由陷阱,核心是TP6/8 + RESTful路由 + JSON响应 + JWT无状态认证;关闭强制路由、显式声明API域名前缀、用think-cors处理跨域、验证码改Redis存储、登录态改JWT实现物理隔离与通信解耦。

ThinkPHP框架支持前后端分离架构,需绕开模板渲染、Session依赖和默认路由陷阱,用TP6/8 + RESTful路由 + JSON响应 + JWT无状态认证实现前后端物理隔离与通信解耦。
关闭模板渲染与默认HTML输出
ThinkPHP默认走index/index控制器并尝试渲染HTML模板,若未显式禁用,接口会返回HTML乱码或直接500报错。
打开config/app.php,将'default_return_type' => 'html'改为'default_return_type' => 'json'。
在route/app.php中删除所有类似Route::rule('/', 'index/index')的兜底路由——这类写法会让/api/user也被重定向到前端控制器,导致接口404。
立即学习“PHP免费学习笔记(深入)”;
【关键前提】控制器必须继承think\Controller,且每个方法末尾显式调用return json($data);任何调用$this->fetch()或view()的操作都会中断JSON输出流。
配置RESTful API路由与域名隔离
前端静态资源由Nginx/Apache直托管,后端只暴露/api/开头的JSON接口,两者可部署在不同域名或端口。
第一步:关闭强制路由,在config/route.php中设'url_route_must' => false,否则未定义路径直接404,无法fallback。
第二步:用闭包统一接管前端路由,但必须加->ext('html')防止匹配到.json后缀接口:Route::rule('[:path]', 'index/index')->ext('html');
第三步:显式声明API域名与前缀,避免被前端路由吞掉:Route::domain('api', function () { Route::group('v1', function () { Route::get('user', 'api/v1/User/index'); }); });
别用@^/:path$正则通配——它会把/api/login也重定向到index/index,接口永远收不到请求。
启用CORS跨域支持(think-cors扩展)
浏览器发起跨域请求时,先发OPTIONS预检;ThinkPHP默认不处理,必须用官方扩展统一放行。
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
方法一:安装扩展composer require topthink/think-cors,在app/middleware.php中注册\think\middleware\Cors::class。
方法二:在config/cors.php中配置合法源,【生产环境严禁写['*']】:'origin' => ['http://localhost:8080', 'https://fe.example.com']。
若前端带Cookie或Authorization头,必须设'allow_credentials' => true,此时origin不能为*,否则浏览器直接拒绝。
Vue开发时Axios请求需加withCredentials: true;JWT场景下可关掉credentials,改用Authorization: Bearer xxx传token。
替换Session为无状态登录态
跨域下Session Cookie无法自动携带,$this->session->get()永远返回null,验证码、登录态全部失效。
验证码改用Redis存储并传递唯一captcha_id:生成时返回['captcha_id' => 'abc123', 'image' => 'data:image/png;base64,...'],校验时从redis.get('captcha:abc123')取值比对,查完立刻DEL防重放。
登录态弃用Session,改用JWT:安装composer require firebase/php-jwt,登录成功后签发token,前端存localStorage,每次请求在Header加Authorization: Bearer xxx。
后端用$request->header('authorization')提取token,不要依赖$this->request->param()或input()——TP6/8中input()已废弃。
前端POST参数接收失败怎么办
Axios默认发application/json,而$this->request->param()只解析表单格式,必然为空。
方法一(推荐):后端改用原始读取:$raw = $this->request->getContent(); $data = json_decode($raw, true) ?: [];
方法二:前端改发表单格式,Axios加transformRequest: [(data) => qs.stringify(data)]并手动设Content-Type: application/x-www-form-urlencoded。
注意:TP6/8中$this->request->input()已移除,强行调用会触发Fatal Error。
















