文章目录

PHP REST API:header() 函数与 JSON 响应

发布于 2026-04-05 22:39:46 · 浏览 14 次 · 评论 0 条

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 的第一步。遵循本文的规范,可避免绝大多数因响应格式错误导致的对接问题。

评论 (0)

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

扫一扫,手机查看

扫描上方二维码,在手机上查看本文