PHP直接echo JSON不是真正API,需路径路由、HTTP方法区分、状态码控制及Content-Type头;应统一处理GET/POST/JSON输入,清空缓冲区,用php://input读JSON体,并封装request()函数保障数据获取可靠性。

PHP脚本直接输出JSON不算API接口
单纯用 echo json_encode($data) 输出,没有请求方法区分、没有路径路由、没有状态码控制,只是“能返回JSON”,不是真正意义上的API接口。真正的API需要可预测的访问路径、明确的HTTP方法(GET/POST)、统一的错误响应格式,以及可被其他系统稳定调用的能力。
常见错误现象:file_get_contents('http://localhost/api/user.php?id=123') 调用成功,但换个参数就500;前端反复刷新出现乱码;POST数据收不到;跨域直接被浏览器拦截——这些都不是JSON没打好,是缺少基础API契约。
- 必须设置
Content-Type: application/json; charset=utf-8响应头,否则前端response.json()可能解析失败 - 不要依赖
$_GET或$_POST直接取值,要先判断请求方法,再决定从哪里读数据(GET参数 / POST表单 / JSON body) - 所有输出前清空缓冲区:
ob_end_clean(),避免BOM或意外空格导致JSON解析失败
用原生PHP写最小可用API路由(不依赖框架)
不需要引入Laravel或ThinkPHP,几行代码就能支撑基础路由。关键是把「路径 → 处理函数」映射起来,并统一处理输入输出。
示例结构(api/index.php):
立即学习“PHP免费学习笔记(深入)”;
'/api/users', 'method' => 'GET', 'handler' => function() {
echo json_encode(['users' => [['id' => 1, 'name' => 'Alice']]]);
}],
['path' => '/api/users', 'method' => 'POST', 'handler' => function() {
$input = json_decode(file_get_contents('php://input'), true) ?: [];
echo json_encode(['status' => 'created', 'id' => rand(100, 999)]);
}]
];
foreach ($routes as $route) {
if ($route['path'] === $path && $route['method'] === $method) {
$route['handler']();
exit;
}
}
http_response_code(404);
echo json_encode(['error' => 'Not Found']);
注意:php://input 是读取原始POST body的唯一可靠方式,$_POST 对JSON无效;parse_url(..., PHP_URL_PATH) 避免把查询参数混进路由判断。
GET/POST/JSON body数据怎么统一获取
前端可能用 fetch('/api/user', { method: 'POST', body: JSON.stringify(...) }),也可能用表单提交,后端不能假设数据来源。得按请求类型智能解析。
- GET请求:只从
$_GET读,忽略body - POST且
Content-Type: application/x-www-form-urlencoded:用$_POST - POST且
Content-Type: application/json:必须用file_get_contents('php://input')+json_decode() - 始终校验
json_last_error() === JSON_ERROR_NONE,否则返回400并提示"Invalid JSON"
别写 if ($_POST) { ... } 这种判断——空表单POST时 $_POST 为空数组,但JSON body可能非空。
为什么建议加一层简单封装(比如 request() 函数)
每次都要判断 Content-Type、读 php://input、做 json_decode、检查错误,重复代码多且易漏。抽一个 request() 函数能立刻降低出错率。
示例(放在公共文件里):
function request($key = null) {
static $data = null;
if ($data === null) {
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'GET') {
$data = $_GET;
} elseif ($method === 'POST') {
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
if (stripos($contentType, 'application/json') !== false) {
$raw = file_get_contents('php://input');
$data = json_decode($raw, true) ?: [];
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
die(json_encode(['error' => 'Invalid JSON']));
}
} else {
$data = $_POST;
}
} else {
$data = [];
}
}
return $key ? ($data[$key] ?? null) : $data;
}
之后在路由处理器里直接写 $id = request('id'); 就行。这个函数不解决鉴权、限流、验证等复杂问题,但它把“数据怎么来”这件事稳住了——这是API能长期维护的底线。
最容易被忽略的是:没设 Content-Type 头、没处理BOM、对空JSON body不做容错、把 $_POST 当万能输入源。这几个点卡住,前端连最基础的 .json() 都会报错。











