应使用 $request->query()->get() 安全获取纯 GET 参数,因 ->get() 仅读取 $_GET,而 ->input() 会合并 POST/JSON 数据导致污染;宏注册需在服务提供者中调用 $this->query(),不可用 all() 或混淆路由参数。

为什么不能直接用 $request->get() 安全取 GET 参数
因为 $request->get() 只读取 $_GET,不合并 POST 或 JSON 数据;而 $request->input() 是 Laravel 推荐的统一入口,自动合并 query、post、json 三层数据。但如果你明确只要 GET 参数(比如做 URL 签名验证、白名单过滤、或兼容旧接口),用 input() 就可能误取到 POST 里的同名字段,导致逻辑错乱。
如何用宏注册一个只取 GET 参数的 getQueryOnly() 方法
必须在服务提供者中注册,且确保闭包内调用的是 $this->query() —— 这是 Symfony 原生方法,返回 ParameterBag 实例,只含 URL 查询参数(即 $_GET)。
- 在
app/Providers/AppServiceProvider.php的boot()方法里写:
<pre class="brush:php;toolbar:false;">use Illuminate\Http\Request;
Request::macro('getQueryOnly', function (string $key, $default = null) {
return $this->query()->get($key, $default);
});
- 调用时:
request()->getQueryOnly('page') 或$request->getQueryOnly('sort', 'asc') - 注意:不能传数组键如
'filters[name]'——query()->get()不支持点语法解析嵌套,需手动parse_str()或用$request->query->all()后自行处理 - 若需支持默认值 + 点语法,得自己实现解析逻辑,宏里不能直接复用
input()的底层逻辑
扩展多个 GET 相关方法时容易踩的坑
常见错误是把 query() 和 all() 混用,或忽略请求类型判断导致取到空值。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
-
$this->query()->all()返回纯 GET 参数数组,但若当前是 POST+JSON 请求且没带 query 字符串,它会返回空数组 —— 不报错也不提示,容易被当成“没传参” - 不要在宏里写
$this->all()再过滤 key,那又绕回了 input 的合并行为,失去“只取 GET”的意义 - 如果路由中有参数如
/users/{id},query()不包含id—— 它只管 URL ? 后面的部分,路由参数得用$request->route('id') - 宏注册必须在所有请求处理前完成,不能放在中间件或控制器里动态注册,否则调用时会抛出
BadMethodCallException
实际场景中要不要用宏?看这三点
宏不是银弹。当项目里只有一两个地方需要严格区分 GET 来源,直接用 $request->query()->get('x') 更轻量;只有当你频繁需要封装逻辑(比如加日志、加白名单校验、自动 trim)、或要统一替换旧代码中的 $_GET 引用时,宏才真正值得投入。
- 如果只是临时取值,别为了一行
$request->query()->get('foo')去写宏注册 + 测试 + 文档 - 如果后续还要支持强制类型转换(如
getQueryInt('limit')),建议把这类方法收拢到一个SafeQuerytrait 或 service 类里,比分散注册多个宏更易维护 - 宏一旦注册就全局生效,命名冲突风险真实存在 —— 比如你定义了
getOnly(),未来 Laravel 版本万一原生加了同名方法,升级就会崩










