日常跳转统一用 redirect(),jump() 是 TP5 遗留函数,仅在模板中配合 success()/error() 使用,TP6 中已不推荐且默认不生效。

ThinkPHP 6 的 redirect() 和 jump() 到底用哪个
直接说结论:日常跳转统一用 redirect(),jump() 是 TP5 时代遗留的、仅在模板里配合 success()/error() 使用的辅助函数,TP6 中已不推荐且默认不生效。
原因很简单:redirect() 是底层 HTTP 重定向(302),走的是标准响应头;而 jump() 实际是渲染一个带 JS 跳转的 HTML 页面,属于前端伪跳转——它依赖模板引擎、需要输出 HTML、无法在 JSON 接口或 CLI 场景下使用。
-
redirect()支持链式调用,比如redirect('user/profile')->with('msg', '更新成功') -
jump()必须在控制器中先调用$this->success()或$this->error(),再由模板里的{:jump()}解析,TP6 默认模板里甚至没这个标签 - 如果误用
jump()在 API 控制器里,会直接抛出TemplateNotFoundException
redirect() 的三种常用写法和参数陷阱
redirect() 看似简单,但路径写错、协议漏写、参数丢失是高频问题。它本质是封装了 Response::create()->redirect(),所有行为都受路由和 URL 生成规则影响。
- 跳转到路由名(推荐):
redirect('index/user/index')—— 路径按模块/控制器/方法写,不加index.php,不写域名 - 跳转到完整 URL:
redirect('https://example.com/login')—— 必须带协议,否则会被当成相对路径拼到当前域名下 - 带参数跳转:
redirect('order/detail', ['id' => 123, 'tab' => 'log'])—— 参数自动拼成 query string,但不会编码中文,中文参数建议先用urlencode()手动处理 - 注意:TP6 默认开启
url_html_suffix,如果配置了后缀(如.html),redirect('article/read')会跳到/article/read.html,不是 bug,是设计行为
为什么 $this->redirect() 有时没反应?常见静默失败场景
最常遇到的是“写了 redirect 却页面没跳、也没报错”,本质是响应已被发送,HTTP 头无法再修改。ThinkPHP 对此不做拦截,而是静默忽略重定向指令。
立即学习“PHP免费学习笔记(深入)”;
- 控制器里提前
echo、var_dump()或开启了调试模式导致输出了调试信息 - 前置中间件里调用了
Response::create()->send()或写了exit - 在
__destruct()或finally块里调用redirect()—— 此时响应早已结束 - 使用了 Swoole 或 RoadRunner 等常驻进程服务器时,
redirect()仍有效,但需确保没有其他协程/线程并发写响应
API 接口里不能用 redirect()?那怎么“跳转”
API 场景下,redirect() 没有意义——前端要的是 JSON,不是 302 响应头。这时候所谓“跳转”其实是前端逻辑,后端只需返回状态和目标地址即可。
- 返回结构示例:
return json(['code' => 302, 'url' => '/login?from=' . urlencode($request->url())]) - 不要在 API 方法里调用
redirect(),否则会强制返回 302 响应,破坏前后端约定 - 如果必须兼容 Web + API,可用
Request::isAjax()或Request::header('accept')判断请求类型,再分支处理 - 注意:部分前端框架(如 Vue Router)对 302 响应不自动跳转,仍需手动解析响应头或 JSON 字段
真正容易被忽略的是:ThinkPHP 的跳转不是“功能开关”,而是 HTTP 协议层的一次响应决策。什么时候该由后端发 302,什么时候该由前端控制路由,边界一旦模糊,后面排查就全是幻觉。











