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

PHP 簡易 Mock JSON 服務腳本:支援 JSONP、CORS、字符集、動態資料源

     編輯:PHP 相關知識

前後端分離開發中,後端 API 未就緒時,前端需要可用的 Mock 資料。本文提供一個單檔案、零依賴的 PHP Mock 服務,支援 JSON/JSONP、跨域 (CORS)、字符集切換、外部 JSON 檔案資料源,適合快速接入測試。

核心功能

  • 預設內建示例資料,無需配置即可運行
  • 偵測 mock.json 檔案,存在則載入作為資料源
  • 支援 callback 參數輸出 JSONP (跨域舊瀏覽器)
  • 支援 cross-domain=1 輸出 CORS Header
  • 支援 charset 參數切換輸出編碼 (utf-8/gbk/gb2312)
  • 統一 Content-Type 輸出

完整代碼:mock.php

<?php
/**
 * Mock JSON API Service
 * 支援:JSON/JSONP、CORS、charset、外部 mock.json
 * 使用:https://host/mock.php?callback=fn&cross-domain=1&charset=utf-8
 */

// 1. 定義常數
define('PARAM_CHARSET', 'charset');
define('PARAM_CALLBACK', 'callback');
define('PARAM_CROSS_DOMAIN', 'cross-domain');

// 2. 獲取 Mock 資料
function getMockData(): string
{
    $mockFile = __DIR__ . '/mock.json';
    if (file_exists($mockFile)) {
        $content = file_get_contents($mockFile);
        // 驗證 JSON 合法性
        json_decode($content);
        if (json_last_error() === JSON_ERROR_NONE) {
            return $content;
        }
        // JSON 無效時回退預設
    }
    
    // 預設示例資料
    $default = [
        'code' => 200,
        'message' => 'success',
        'data' => [
            'id' => 1,
            'username' => 'demo_user',
            'email' => 'demo@example.com',
            'roles' => ['user', 'editor'],
            'profile' => [
                'avatar' => 'https://example.com/avatar.png',
                'nickname' => 'Demo User'
            ]
        ],
        'timestamp' => time(),
        'request_id' => uniqid('req_', true)
    ];
    return json_encode($default, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}

// 3. 解析字符集參數
function getCharset(): string
{
    $charset = strtolower($_GET[PARAM_CHARSET] ?? 'utf-8');
    return in_array($charset, ['utf-8', 'gbk', 'gb2312'], true) ? $charset : 'utf-8';
}

// 4. 組裝輸出
function generateResponse(): string
{
    $data = getMockData();
    $charset = getCharset();
    $callback = $_GET[PARAM_CALLBACK] ?? '';
    $crossDomain = isset($_GET[PARAM_CROSS_DOMAIN]);
    
    if ($callback !== '') {
        // JSONP 輸出
        // 簡單驗證 callback 合法性 (僅字母數字底線點)
        if (!preg_match('/^[\w.]+$/', $callback)) {
            $callback = 'callback';
        }
        header('Content-Type: application/javascript; charset=' . $charset);
        return $callback . '(' . $data . ');';
    } else {
        // 標準 JSON
        if ($crossDomain) {
            header('Access-Control-Allow-Origin: *');
            header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
            header('Access-Control-Allow-Headers: Content-Type, Authorization');
        }
        header('Content-Type: application/json; charset=' . $charset);
        return $data;
    }
}

// 5. 處理 OPTIONS 預檢
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
    header('Access-Control-Allow-Headers: Content-Type, Authorization');
    header('Access-Control-Max-Age: 86400');
    exit(0);
}

// 6. 輸出
echo generateResponse();

外部資料源:mock.json

在同目錄建立 mock.json,即自動載入:

{
  "code": 200,
  "message": "操作成功",
  "data": {
    "list": [
      {"id": 1, "title": "文章一", "views": 1234},
      {"id": 2, "title": "文章二", "views": 5678}
    ],
    "pagination": {"page": 1, "page_size": 20, "total": 2}
  }
}

使用場景與參數說明

場景請求範例說明
前端直連 (同域)fetch('/mock.php').then(r=>r.json())標準 JSON
跨域 (現代瀏覽器)fetch('https://api.mock/mock.php?cross-domain=1')CORS Header
跨域 (舊瀏覽器/JSONP)<script src="https://api.mock/mock.php?callback=handleData"></script>JSONP 回調
指定編碼 (舊系統)/mock.php?charset=gbk輸出 GBK 編碼
動態資料修改 mock.json 即時生效無需重啟服務

進階擴展建議

1. 支援多 API 端點路由

$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$routes = [
    '/api/user/profile' => 'mocks/user_profile.json',
    '/api/articles' => 'mocks/articles.json',
    '/api/comments' => 'mocks/comments.json',
];
$mockFile = __DIR__ . '/' . ($routes[$path] ?? 'mock.json');

2. 支援請求參數動態過濾資料

$data = json_decode(getMockData(), true);
if (isset($_GET['page'], $_GET['page_size'])) {
    $page = (int)$_GET['page'];
    $size = (int)$_GET['page_size'];
    if (isset($data['data']['list'])) {
        $data['data']['list'] = array_slice($data['data']['list'], ($page-1)*$size, $size);
        $data['data']['pagination'] = ['page'=>$page, 'page_size'=>$size, 'total'=>count($data['data']['list'])];
    }
}
echo json_encode($data);

3. 支援延遲模擬 (模擬網路慢)

if (isset($_GET['delay'])) {
    $delay = min(max((int)$_GET['delay'], 0), 5000); // 0-5000ms
    usleep($delay * 1000);
}

4. 整合到現有框架 (Laravel 路由範例)

// routes/web.php
Route::any('/mock/{any?}', function ($any = null) {
    $mockFile = base_path("mocks/{$any}.json");
    if (!file_exists($mockFile)) $mockFile = base_path('mocks/default.json');
    // ... 同邏輯輸出
})->where('any', '.*');

對比:為何不直接訪問靜態 .json 檔案?

能力靜態 .jsonPHP Mock 腳本
JSONP 回調❌✅
CORS Header❌ (需 Web 伺服器配置)✅ 程式控制
字符集轉換❌✅
動態參數過濾❌✅
延遲/錯誤模擬❌✅
請求日誌/統計❌✅

部署建議

  • 放置於獨立子域或路徑前綴 (如 /mock/),避免衝突正式 API
  • 生產環境**務必移除或加密碼保護**,防洩露測試資料結構
  • 配合 nginx location /mock/ { ... } 限制存取 IP
  • 團隊約定:Mock 資料結構與正式 API 契約保持一致

這個 50 行的 PHP 腳本,解決了前端等待後端 API 的阻塞問題,支援主流跨域方案與編碼需求,是前後端並行開發的輕量級利器。

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