old() 通过读取 session 中的 old.$key 键获取上一次输入值,依赖 withInput() 在重定向前将请求数据以 flash 方式存入 session,仅在下一次请求中有效。

old() 是怎么拿到上一次输入值的
old() 不是凭空读取浏览器历史或表单缓存,它依赖 Laravel 的 session 机制。具体来说,它等价于从 session 中读取 old.$key 这个键对应的值。比如调用 old('email'),底层就是执行 session('old.email')。
这个 old 键的内容不是自动产生的,必须由开发者在重定向前显式写入——最常见的方式就是在控制器验证失败后调用 withInput() 方法。
-
withInput()实际调用的是session()->flash('old', $request->all()) -
flash()表示该数据只在下一次请求中有效,之后自动销毁(即“一次性 session”) - 如果没调用
withInput()或类似逻辑,old()永远返回null,哪怕表单刚提交过
为什么 old() 在 redirect()->back() 后才生效
因为 old() 读取的是「当前请求」的 session 数据,而用户提交表单后触发验证失败,Laravel 默认会重定向(HTTP 302)到原页面。只有在这个新请求里,session 才已加载上一轮写入的 old 数据。
换言之:提交 → 验证失败 → 重定向 → 新请求开始 → session 加载 → old() 可读。
- 如果你用
return view('form', [...])直接渲染(不重定向),old()会为空,因为没有经过 session flash 流程 - 即使手动在 session 写了
old,也要确保写入发生在重定向之前,且 key 结构匹配(如嵌套字段需用点号表示:old('address.city')) - Blade 模板中
old('name')和old('name', 'default')的第二个参数仅在 session 无值时起作用,不会覆盖已有值
容易被忽略的三个边界情况
多数人以为只要用了 withInput() 就万事大吉,但实际部署中常因以下原因导致回填失效:
- 中间件清除了 session:比如自定义认证中间件中调用了
session()->flush()或未启用 session 驱动 - 表单 method 不是 POST/PUT/PATCH:Laravel 默认只对这些方法的请求调用
withInput();GET 请求提交的参数不会被自动 flash - CSRF token 失效或缺失:会导致整个请求被拦截,根本走不到控制器的
withInput()这一步,自然也没有old()数据可读
真正关键的链路是:表单提交 → CSRF 校验通过 → 控制器执行 → 验证失败 → withInput() 写入 session → 重定向响应发出 → 浏览器发起新请求 → session 加载 → 视图中 old() 可用。任一环节断裂,回填就断了。


















