PHP REST API:header() 函数与 JSON 响应
在构建 RESTful API 时,正确设置 HTTP 响应头和返回 JSON 数据是最基础也是最关键的环节。很多初学者在这两步上容易出错,导致客户端无法正确解析数据或遭遇跨域问题。本文将系统讲解 header() 函数的使用方法以及 JSON 响应的正确返回姿势。
一、HTTP 响应头的基础认知
在深入代码之前,先明确几个核心概念。HTTP 响应由状态行、响应头和响应体三部分组成。响应头告诉浏览器或客户端"这个响应是什么类型"、"是否允许缓存"、"是否支持跨域"等元信息。
| 响应头名称 | 作用说明 |
|---|---|
Content-Type |
声明响应体的媒体类型,告诉客户端如何解析数据 |
Access-Control-Allow-Origin |
处理跨域请求,允许哪些域名访问接口 |
Cache-Control |
控制缓存策略,如 no-cache 表示不缓存 |
Status |
HTTP 状态码,如 200 表示成功,`404 表示资源不存在 |
Content-Type 是 JSON API 中最重要的响应头。正确设置它,客户端才能将响应体识别为 JSON 并自动解析。
二、header() 函数的核心用法
PHP 使用 header() 函数来发送原始 HTTP 响应头。必须在任何实际输出(包括空格、UTF-8 BOM)之前调用,否则会触发 "Headers already sent" 错误。
2.1 设置 Content-Type
<?php
header('Content-Type: application/json; charset=utf-8');
// 之后返回 JSON 数据
echo json_encode(['status' => 'success', 'data' => []]);
解释一下这行代码的含义:Content-Type 声明响应体是 JSON 格式,charset=utf-8 确保中文等非 ASCII 字符正确传输。
2.2 设置状态码
HTTP 状态码决定请求的成败。PHP 默认返回 200,需要手动设置其他状态码:
<?php
// 设置 404 状态码
header('Content-Type: application/json; charset=utf-8');
http_response_code(404);
echo json_encode(['error' => '资源不存在']);
注意:http_response_code() 是设置状态码的标准方法,而非通过 header()。
2.3 处理跨域请求
前后端分离项目中,浏览器会检查 Access-Control-Allow-Origin 头来处理跨域问题:
<?php
header('Access-Control-Allow-Origin: *'); // 允许所有域名访问
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
// 处理 OPTIONS 预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
header('Content-Type: application/json; charset=utf-8');
```
---
## 三、JSON 响应的正确返回方式
### 3.1 使用 `json_encode()` 编码数据
`json_encode()` 将 PHP 数组或对象转换为 JSON 字符串:
```php
<?php
$data = [
'status' => 'success',
'code' => 200,
'message' => '操作成功',
'data' => [
['id' => 1, 'name' => '产品A'],
['id' => 2, 'name' => '产品B']
]
];
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data, JSON_UNESCAPED_UNICODE);
```
`JSON_UNESCAPED_UNICODE` 参数确保中文不会被转义为 Unicode 编码,直接输出可读的中文字符。
### 3.2 处理 JSON 编码错误
`json_encode()` 在编码失败时返回 `false`。生产环境必须捕获这类错误:
```php
<?php
function jsonResponse($data, $statusCode = 200) {
header('Content-Type: application/json; charset=utf-8');
http_response_code($statusCode);
$result = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
if ($result === false) {
$result = json_encode([
'status' => 'error',
'message' => 'JSON 编码失败',
'debug' => json_last_error_msg()
], JSON_UNESCAPED_UNICODE);
}
echo $result;
exit;
}
// 使用示例
jsonResponse(['status' => 'success', 'data' => ['id' => 1]], 200);
```
这个封装函数统一处理了响应格式,避免重复写 `header()` 和 `json_encode()`。
---
## 四、常见错误与解决方案
### 4.1 "Headers already sent" 错误
这个错误发生在 `header()` 调用前有任何输出。常见原因及排查方法:
| 原因 | 解决方法 |
| :--- | :--- |
| `header.php` 文件开头有空行 | 删除文件开头的空行和空格 |
| UTF-8 BOM 标记 | 用纯文本编辑器保存为"无 BOM"格式 |
| 在 `header()` 前有 `echo` 或 `print` | 调整代码顺序,确保 `header()` 最早执行 |
排查技巧:在可能输出内容的第一行前加 `ob_start();` 开启输出缓冲,可临时绕过此问题,但根本解决还是要找到输出源。
### 4.2 JSON 数据被转义
默认情况下,中文字符会被转义为 `\uXXXX` 格式。解决方案是使用 `JSON_UNESCAPED_UNICODE`:
```php
<?php
// 中文被转义的情况
echo json_encode(['name' => '中国']); // {"name":"\u4e2d\u56fd"}
// 中文正常显示
echo json_encode(['name' => '中国'], JSON_UNESCAPED_UNICODE); // {"name":"中国"}
```
### 4.3 响应被浏览器缓存
部分浏览器会缓存 GET 请求的响应,导致数据更新后页面仍显示旧数据:
```php
<?php
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
echo json_encode(['data' => getFreshData()]);
```
---
## 五、完整的 API 响应封装示例
将上述知识点整合成一个可直接复用的 API 基础类:
```php
<?php
class ApiResponse {
/**
* 输出成功响应
*/
public static function success($data = null, $message = '操作成功') {
self::json([
'status' => 'success',
'code' => 200,
'message' => $message,
'data' => $data
], 200);
}
/**
* 输出错误响应
*/
public static function error($message, $code = 400, $debug = null) {
$response = [
'status' => 'error',
'code' => $code,
'message' => $message
];
if ($debug !== null && DEBUG_MODE === true) {
$response['debug'] = $debug;
}
self::json($response, $code);
}
/**
* 输出 404 响应
*/
public static function notFound($message = '资源不存在') {
self::error($message, 404);
}
/**
* 内部统一输出方法
*/
private static function json($data, $httpCode) {
http_response_code($httpCode);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
exit;
}
}
// 使用示例
// ApiResponse::success(['id' => 1, 'name' => '示例']);
// ApiResponse::error('参数错误', 400);
// ApiResponse::notFound();
六、调试与验证
开发完成后,使用工具验证 API 响应是否正确。curl 命令是最便捷的测试方式:
curl -i http://your-api-endpoint.com/endpoint
-i 参数会同时输出响应头和响应体,检查 Content-Type 是否为 application/json,状态码是否正确。
也可以在代码中添加调试输出:
<?php
header('Content-Type: application/json; charset=utf-8');
// 调试模式:输出请求方法
if (DEBUG) {
$debugInfo = [
'method' => $_SERVER['REQUEST_METHOD'],
'uri' => $_SERVER['REQUEST_URI'],
'params' => $_GET
];
}
echo json_encode($data, JSON_UNESCAPED_UNICODE);
掌握 header() 函数与 JSON 响应的正确用法,是构建可靠 REST API 的第一步。遵循本文的规范,可避免绝大多数因响应格式错误导致的对接问题。

暂无评论,快来抢沙发吧!