首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 產生 JSON 與 XML 格式 API 回應資料統一類別

     編輯:PHP 綜合知識

前言

API 開發需統一回應格式,便於前端消費、錯誤處理、文件生成。本文設計 Response 類別,支援 JSON/XML 雙格式輸出、標準化碼/訊息/資料結構、巢狀資料 XML 序列化,並提供測試範例。

一、Response 類別完整實作

<?php
class Response {
    /**
     * 統一輸出入口
     * @param int    $code    狀態碼 (200=成功, 4xx=客戶端錯誤, 5xx=伺服器錯誤)
     * @param string $message 提示訊息
     * @param mixed  $data    回傳資料 (陣列/物件/標量)
     * @param string $format  輸出格式: 'json' | 'xml' | '' (自動判斷)
     * @return string 格式化後字串
     */
    public static function show($code, $message, $data = [], $format = '') {
        if (!is_numeric($code)) return '';
        
        $result = [
            'code'    => (int)$code,
            'message' => (string)$message,
            'data'    => $data,
        ];
        
        $format = strtolower($format);
        if ($format === 'json') {
            return self::toJson($result);
        } elseif ($format === 'xml') {
            return self::toXml($result);
        }
        
        // 自動判斷:依 Accept 標頭或預設 JSON
        $accept = $_SERVER['HTTP_ACCEPT'] ?? '';
        return (strpos($accept, 'xml') !== false) ? self::toXml($result) : self::toJson($result);
    }
    
    /**
     * JSON 輸出
     */
    public static function toJson($result) {
        // 設定標頭
        if (!headers_sent()) {
            header('Content-Type: application/json; charset=utf-8');
        }
        // JSON_UNESCAPED_UNICODE: 中文不轉 \uXXXX
        // JSON_UNESCAPED_SLASHES: / 不轉 \/
        return json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }
    
    /**
     * XML 輸出
     */
    public static function toXml($result) {
        if (!headers_sent()) {
            header('Content-Type: application/xml; charset=utf-8');
        }
        
        $xml = "\n";
        $xml .= "\n";
        $xml .= self::arrayToXml($result);
        $xml .= "";
        return $xml;
    }
    
    /**
     * 陣列遞迴轉 XML
     * @param array $data
     * @param string $root 根節點名
     * @return string
     */
    protected static function arrayToXml($data, $root = 'item') {
        $xml = '';
        foreach ($data as $key => $value) {
            // 數字鍵轉為 ...
            $attr = '';
            $nodeName = $key;
            if (is_numeric($key)) {
                $attr = " id=\"$key\"";
                $nodeName = $root;
            }
            // 節點名安全化:只保留字母數字底線
            $nodeName = preg_replace('/[^a-zA-Z0-9_]/', '_', $nodeName);
            if ($nodeName === '') $nodeName = $root;
            
            $xml .= "<$nodeName$attr>";
            if (is_array($value) || is_object($value)) {
                $xml .= "\n" . self::arrayToXml((array)$value, $nodeName) . "\n";
            } else {
                // CDATA 保護特殊字元
                $xml .= "";
            }
            $xml .= "\n";
        }
        return $xml;
    }
}
?>

二、使用範例

<?php
require_once 'Response.php';

// 模擬資料
$grade = [
    "score" => [70, 95, 70.0, 60, "70"],
    "name"  => ["張三", "李四", "王五", "趙六", "天齊"],
    "meta"  => [
        "total" => 5,
        "avg"   => 73.0,
        "pass"  => true
    ]
];

// 1. JSON 輸出
echo Response::show(200, 'success', $grade, 'json');
/* 輸出:
{
    "code": 200,
    "message": "success",
    "data": {
        "score": [70, 95, 70, 60, "70"],
        "name": ["張三", "李四", "王五", "趙六", "天齊"],
        "meta": {"total": 5, "avg": 73, "pass": true}
    }
}
*/

// 2. XML 輸出
echo Response::show(200, 'success', $grade, 'xml');
/* 輸出:


200




...

...







*/

// 3. 錯誤回應
echo Response::show(404, 'User not found', null, 'json');
// {"code":404,"message":"User not found","data":null}

// 4. 直接輸出到瀏覽器(API 入口)
// Response::show(200, 'OK', $data);  // 自動判斷格式
?>

三、進階擴充:HTTP 狀態碼對應、例外整合

<?php
class ApiResponse extends Response {
    // 常用狀態碼常數
    const OK = 200;
    const CREATED = 201;
    const BAD_REQUEST = 400;
    const UNAUTHORIZED = 401;
    const FORBIDDEN = 403;
    const NOT_FOUND = 404;
    const VALIDATION_ERROR = 422;
    const SERVER_ERROR = 500;
    
    // 成功快捷方法
    public static function success($data = [], $message = 'OK', $format = '') {
        return self::show(self::OK, $message, $data, $format);
    }
    
    // 驗證失敗
    public static function validationError($errors, $message = 'Validation failed', $format = '') {
        return self::show(self::VALIDATION_ERROR, $message, ['errors' => $errors], $format);
    }
    
    // 伺服器錯誤
    public static function serverError($message = 'Internal server error', $format = '') {
        return self::show(self::SERVER_ERROR, $message, null, $format);
    }
    
    // 直接輸出並結束腳本(API 入口常用)
    public static function emit($code, $message, $data = [], $format = '') {
        echo self::show($code, $message, $data, $format);
        exit;
    }
}

// 使用
// ApiResponse::emit(ApiResponse::success($userData));
// ApiResponse::emit(ApiResponse::validationError($validator->errors()));
?>

四、XML 序列化細節說明

資料型別XML 表示說明
純量 (string/int/float/bool)<key><![CDATA[value]]></key>CDATA 保護特殊字元
索引陣列<item id="0">...</item>保留順序與索引
關聯陣列/物件<key>...</key>鍵名作為節點名
null<key></key> 或略過可選擇輸出空節點

五、效能與快取建議

  • JSON 编码快取: 相同資料結構重複輸出時,快取 json_encode 結果(key = md5(serialize($data)))。
  • XML 較慢: 遞迴產生字串開銷大,高頻 API 建議預設 JSON,XML 僅按需輸出。
  • 大量資料分頁: 回傳 data: {list: [...], pagination: {page, per_page, total}} 結構,避免單次回傳過大。

六、常見問題

  • 中文變 \uXXXX: 加上 JSON_UNESCAPED_UNICODE 旗標。
  • XML 節點名非法: 鍵名含空格、中文、連字號會導致 XML 無效,已在 arrayToXml 中用正則清理。
  • 布林值輸出: PHP true/false → JSON true/false,XML 1/0 (CDATA 內),前端解析時注意型別轉換。

小結

Response 類別提供 統一結構 (code/message/data)、雙格式 (JSON/XML)、自動格式協商、巢狀資料正確序列化。延伸 ApiResponse 加入語意化狀態碼與快捷方法,可直接作為 API 專案基礎元件。生產環境建議搭配 OpenAPI/Swagger 註解 自動生成文件,並加入 回應快取、壓縮 (gzip)、CORS 標頭 完善 API 體驗。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved