分页链接默认丢失手动添加的查询参数,appends() 是唯一可靠方案;它显式声明需保留的参数,自动处理编码与去重,但 API 分页需手动重设 next_page_url。

分页链接默认会丢掉你手动加的查询参数,appends() 是唯一靠谱的补救方式。
为什么分页后 ?search=xxx 消失了
Laravel 的 paginate() 只保留当前请求的路由参数(比如 /users?page=2 中的 page),所有其他查询参数(search、status、sort 等)默认不带进下一页链接。这不是 bug,是设计如此——框架不知道哪些参数该“继承”。
常见错误现象:
用户在搜索框输入 “admin”,点击第 2 页,URL 变成 /users?page=2,搜索条件没了,结果全乱了。
- 别试图用
request()->fullUrlWithQuery()手动拼分页链接——它会把page也重复塞进去,导致?page=2&page=3 - 别在控制器里先
request()->except('page')再传给视图——视图里调$users->appends(...)更干净、更解耦
appends() 怎么用才不翻车
appends() 接收数组或键值对,把你想保留的查询参数“显式声明”给分页器。它会自动处理 URL 编码和去重。
最常用写法:
$users = User::where('active', 1)->paginate(15)->appends(request()->except('page'));
但要注意几个细节:
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
- 如果只追加某几个字段,比如只留
search和status:->appends(['search' => request('search'), 'status' => request('status')]) - 如果参数值可能为空(比如
request('search') === null),appends()仍会把它转成?search=,建议先过滤:request()->filter(['search', 'status'])或手写array_filter(request()->only(['search', 'status'])) - 在 Blade 中直接用
$users->links()即可,它自动渲染带参数的分页 HTML;不用改模板里的href
appends() 在 API 场景下的坑
如果你返回 JSON 分页数据(比如用 response()->json($users)),appends() 不会影响 next_page_url 字段——Laravel 的 API 分页响应默认不继承自定义参数。
必须显式覆盖:
$users = User::paginate(15);
$users->appends(request()->except('page'));
// 但 next_page_url 还是原始值,得手动重设:
if ($users->nextPageUrl()) {
$users->setNextPageUrl($users->nextPageUrl() . '&' . http_build_query(request()->except('page')));
}
更稳妥的做法是:API 不依赖 appends(),而是统一在响应前手动构造分页元数据,避免链式调用带来的不可见副作用。
真正容易被忽略的是:当页面有多个独立筛选区块(比如左侧分类菜单 + 顶部搜索框 + 表格内状态切换),它们的参数可能来自不同来源(GET、AJAX POST、JS history.pushState),appends() 只管当前请求的 query,没法自动合并。这种场景得靠前端统一管理 URL 状态,后端只做“忠实反射”。










