php本身不拦截跨域请求,真正拦截的是浏览器;常见失效原因是credentials: 'include'与access-control-allow-origin: *共存,此时须指定具体域名并设置access-control-allow-credentials: true,且header()必须在任何输出前执行。

PHP 本身不会对 JS 发起的请求做跨域拦截——真正拦住的是浏览器。你看到的 Access to fetch at 'http://api.example.com' from origin 'http://localhost:3000' has been blocked by CORS policy 错误,是浏览器在收到响应后主动丢弃数据,不是 PHP 拒绝了请求。
为什么 header("Access-Control-Allow-Origin: *") 有时不起作用
最常见原因是:前端用了 credentials: 'include'(比如带 Cookie 或 Authorization 头),而 PHP 却写了 Access-Control-Allow-Origin: *。这两者不能共存,浏览器会直接拒绝响应。
- 如果前端需要传 Cookie 或认证头,PHP 必须写具体域名:
header("Access-Control-Allow-Origin: http://localhost:3000"); -
Access-Control-Allow-Credentials: true必须显式设置,且只能配合具体域名使用 - 确保该
header()调用在任何输出(包括空格、BOM、echo、print)之前执行,否则报headers already sent
OPTIONS 预检请求返回 405 或空白怎么办
非简单请求(如 PUT、带 Authorization 头的 POST)会触发浏览器先发一个 OPTIONS 请求。如果 PHP 没处理它,Apache/Nginx 可能直接返回 405(Method Not Allowed)或 404。
- 必须在业务逻辑前加判断:
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; } - Apache 的
.htaccess或 Nginx 配置可能重写了OPTIONS,需确认 rewrite 规则没吞掉它 - 某些 FastCGI 模式下,
$_SERVER['REQUEST_METHOD']在预检时可能不可靠,可改用getenv('REQUEST_METHOD')做兜底
header() 写在哪?多个 PHP 文件怎么统一管
不能只在某个 API 文件里加,得覆盖所有被前端调用的入口点。但逐个改容易漏,也难维护。
- 推荐方式:在公共入口(如
index.php或框架的中间件)统一注入 CORS 头 - Apache 下可用
.htaccess:Header set Access-Control-Allow-Origin "https://your-frontend.com"(需启用mod_headers) - Nginx 下在
location块里加:add_header 'Access-Control-Allow-Origin' 'https://your-frontend.com'; - 注意:Nginx 的
add_header不继承父级,子 location 需重复写或用include抽离
真正麻烦的不是加几行 header(),而是前端发什么请求、带不带凭证、用什么方法——这些决定了 PHP 要配哪几个头、要不要处理 OPTIONS、能不能用通配符。漏掉任意一环,浏览器就静默失败,连 network 面板里都看不出后端有没有响应成功。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











