分页时需用->appends($request->query())保留get搜索参数,因paginator不自动记忆、withinput()仅适用于post、old()对get无效;模板中应使用request('keyword')回填而非old()。

分页时如何保留搜索参数(withInput)
直接在查询后链式调用 appends(),把当前请求的查询参数全部带进分页链接。Laravel 的 Paginator 不会自动记住 GET 参数,不手动追加,翻页后所有搜索条件就丢了。
常见错误是只写 ->paginate(15),结果点第2页变成全量数据;或者用 old() 试图回填表单——但 old() 只对 POST 请求有效,GET 搜索根本不会触发它。
- 必须在控制器里获取原始参数:
$request->query(),而不是$request->all()(后者混入 POST 数据,可能污染分页 URL) - 避免硬编码追加:
->appends(['keyword' => $keyword]),容易漏字段;用->appends($request->query())更稳妥 - 注意键名冲突:如果分页参数名(如
page)和你自己的查询参数重名,appends()会覆盖,但 Laravel 默认处理得当,无需额外规避
Laravel 9+ 中 withInput 不适用于 GET 表单的真相
withInput() 是为 POST 表单设计的,底层依赖 session 存储上一次请求的输入。而搜索表单走的是 GET,参数直接挂在 URL 上,压根不经过 session,所以 withInput() 对搜索无效——这不是 bug,是设计使然。
典型误用场景:用户提交 GET 搜索后刷新页面,或点击分页链接,表单 input 值为空。这时候不是 old() 失效,而是它根本没被写入。
- 正确做法是模板中直接从
$request->query('keyword')或request('keyword')取值填充 input 的value - 不要在控制器里做
return view(...)->withInput(),对 GET 无意义 - 如果搜索表单意外用了 POST,虽能用
withInput(),但破坏 REST 语义、无法收藏/分享链接,不推荐
分页链接生成时过滤敏感或冗余参数
直接 appends($request->query()) 很方便,但如果 URL 里混进了 _token、submit 这类非搜索字段,分页链接会变脏,还可能暴露 CSRF token(虽不影响安全,但不专业)。
更糟的是,某些前端 JS 动态加的参数(如 __t=1712345678 时间戳)也会被透传,导致缓存失效、统计失真。
- 用
array_filter()清洗:appends(array_filter($request->query(), function($k) { return in_array($k, ['keyword', 'status', 'sort']); }, ARRAY_FILTER_USE_KEY)) - 也可以先定义白名单:
$allowed = ['keyword', 'category_id', 'page']; appends(array_intersect_key($request->query(), array_flip($allowed))) - 注意
page参数会被 Paginator 自动处理,不必显式传入,重复传可能导致链接出现两个page=2
Blade 模板里怎么安全回填并渲染分页
回填靠 request('xxx'),分页靠 $users->appends(...)->links(),两者必须用同一套参数源,否则表单值和分页链接不一致——比如搜 “admin” 后点第2页,URL 是 ?keyword=admin&page=2,但表单 input 里却是空的,用户感知就是“断连”了。
另一个坑是 Blade 中直接写 {{ old('keyword') }},在 GET 请求下永远为空,但语法没错,很难排查。
- 表单 input 写法:
<input name="keyword" value="{{ request('keyword') }}"> - 分页组件写法:
{{ $users->appends(request()->query())->links() }} - 如果用了自定义分页视图,确认它接收并透传了
$elements外的$appends参数,否则appends()白做了
old() 和 request() 是多数人卡住的第一步。











