最准确方式是用$request->server('REQUEST_METHOD')获取原始HTTP方法,因它绕过_method伪造和中间件干扰;$request->method(true)在旧版TP6中存在bug,不可靠。

直接用 $request->server('REQUEST_METHOD') 最稳
想准确知道当前请求是 GET、POST 还是其他方法,$request->server('REQUEST_METHOD') 是最底层、最可靠的来源。它读的是 CGI 环境变量,不受任何框架层伪造逻辑干扰(比如 _method 表单伪装)。
常见错误是误用 $request->method() 或 $request->method(true):在 TP6.0.0–6.0.3 等旧版本中,method(true) 仍可能被 _method 参数覆盖,返回 PUT/DELETE 而非真实 HTTP 方法;而 method() 默认就走重写逻辑,更不可靠。
-
$request->server('REQUEST_METHOD')返回原始字符串,如'GET'、'POST'、'OPTIONS' - 建议加默认值防止空:
$request->server('REQUEST_METHOD', 'GET') - 不要依赖
$request->isPost()等快捷方法做统计或权限拦截——它们内部调用的仍是method(),有同样风险
需要区分「真实 POST」和「_method=PUT 的伪装 POST」?
很多接口统计或安全策略要求只处理“真实 POST”,即浏览器或客户端直接发来的 POST 请求,排除 HTML 表单提交时通过 _method=PUT 绕过限制的情况。
此时不能只看 REQUEST_METHOD === 'POST',还要结合参数判断:
立即学习“PHP免费学习笔记(深入)”;
- 如果
$request->server('REQUEST_METHOD') === 'POST'且$request->param('_method', '') === '',才是真实 POST - 若
_method存在且非空(如'PUT'、'DELETE'),说明是表单伪造,应按实际语义处理(如走 PUT 逻辑),或直接拒绝 - 注意:
$request->param()默认从$_POST + $_GET合并读取,确保没被中间件提前清空或过滤
遇到 OPTIONS 预检请求怎么办
前端发带自定义 Header 的请求(如 Authorization: Bearer xxx)时,浏览器会先发一个 OPTIONS 请求。这个请求没有业务意义,但必须正确响应,否则整个请求链中断。
在中间件里快速识别并放行:
- 用
$request->isOptions()判断最直观(本质就是检查REQUEST_METHOD === 'OPTIONS') - 如果是预检,直接返回空响应:
return response('', 204);,不要调用$next($request) - 别忘了设置 CORS 头,尤其是
Access-Control-Allow-Methods和Access-Control-Allow-Headers,漏字段会导致预检失败 - 注意:TP 内置
think\middleware\Cors默认已处理 OPTIONS,但必须注册在业务中间件之前,否则你的权限中间件可能先报错退出
为什么 $request->route() 在某些中间件里是 null
不是所有中间件都能安全调用 $request->route()。它只在路由匹配完成后才可用,而中间件执行顺序决定了这一点。
比如全局中间件(在 app/middleware.php 定义)会在路由解析前就执行,此时 $request->route() 返回 null,调用 getName() 或 getActionName() 会直接报错:Call to a member function getName() on null。
- 需要路由信息的中间件(如权限校验),应注册为「路由中间件」或「控制器中间件」,而非全局中间件
- 若必须在全局中间件里用,先判空:
if ($request->route() !== null) { ... } - 替代方案:用
$request->url()->getPath()或$request->path()做路径匹配,不依赖路由对象
REQUEST_METHOD 的可靠性只建立在 Web Server 正确透传的前提下**。Nginx 反向代理时若没配 fastcgi_param REQUEST_METHOD $request_method;,PHP 就拿不到真实方法——这种问题不会报错,只会静默失真。



















