php直接输出json需同时设置content-type: application/json和access-control-allow-origin等cors响应头,否则浏览器会拦截;若前端带credentials,origin不能为*且须配allow-credentials:true。

PHP 直接输出 JSON 时浏览器报 CORS 错误
默认情况下,PHP 脚本返回 Content-Type: text/html,即使你用了 json_encode(),前端 fetch 或 axios 仍会因缺少响应头被浏览器拦截。关键不是“怎么转 JSON”,而是“怎么让浏览器接受这个 JSON 响应”。
- 必须显式设置
Content-Type: application/json -
跨域必需加
Access-Control-Allow-Origin响应头 - 如果前端带 credentials(如 cookie),还需加
Access-Control-Allow-Credentials: true,此时Access-Control-Allow-Origin不能为*,得写具体域名
最简可用的跨域 JSON 返回代码
以下代码适用于调试或简单接口,不带鉴权、不处理预检请求(OPTIONS):
<?php
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
// 如果前端用了 withCredentials,把上面这行换成:
// header('Access-Control-Allow-Origin: https://your-frontend-domain.com');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, X-Requested-With');
$data = ['code' => 0, 'msg' => 'ok', 'data' => ['id' => 123]];
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
?>
注意:JSON_UNESCAPED_UNICODE 避免中文变 \uXXXX;JSON_UNESCAPED_SLASHES 防止 URL 斜杠被转义。
遇到 OPTIONS 预检失败怎么办
当请求含自定义 header(如 Authorization)或 method 为 PUT/DELETE 时,浏览器先发 OPTIONS 请求。若后端没响应,就卡住。
立即学习“PHP免费学习笔记(深入)”;
- 检查是否漏了
Access-Control-Allow-Methods和Access-Control-Allow-Headers - 对 OPTIONS 请求可直接 exit,无需业务逻辑:
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { exit(); } - Apache 用户可在 .htaccess 加
Header set Access-Control-Allow-Origin "*",但 PHP 中设置更可控
生产环境要注意的三个细节
线上用这套逻辑,别直接复制粘贴:
- 不要长期开放
Access-Control-Allow-Origin: *+Access-Control-Allow-Credentials: true,二者互斥,会触发浏览器报错 - 避免在多个地方重复调用
header(),尤其引入其他文件后可能已输出内容,导致headers already sent - 敏感接口建议根据
$_SERVER['HTTP_ORIGIN']白名单校验并动态设置Access-Control-Allow-Origin,而不是硬写死或全放行
跨域真正难的不是加几行 header,而是理解浏览器何时发预检、哪些 header 触发它、credentials 如何影响 Origin 通配符——这些点漏一个,前端就收不到数据。











