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

PHP無法獲取React Native Fetch參數解決方案:Content-Type陷阱與統一兼容處理

     編輯:PHP 綜合知識

React Native fetch 預設發送 Content-Type: application/json,導致 PHP $_POST 為空。本文分析根因,提供前端構建表單數據、後端讀取 php://input 兩類方案,並給出生產級統一兼容中間件代碼(支援iOS/Android/Web多端共存)。

問題根因

fetch('https://api.example.com/endpoint', {
    method: 'POST',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json', // 關鍵:JSON格式
    },
    body: JSON.stringify({ username: 'val', pass: 'val' })
});

PHP $_POST 僅自動解析 application/x-www-form-urlencoded 或 multipart/form-data,不解析 JSON,故為空陣列。

方案一:前端改為表單格式(不推薦,改動大)

function toQueryString(obj) {
    return Object.keys(obj).sort().map(key => {
        const val = obj[key];
        if (Array.isArray(val)) {
            return val.sort().map(v => `${encodeURIComponent(key)}=${encodeURIComponent(v)}`).join('&');
        }
        return `${encodeURIComponent(key)}=${encodeURIComponent(val)}`;
    }).join('&');
}
// fetch body: toQueryString(obj)
// headers['Content-Type'] = 'application/x-www-form-urlencoded'

方案二:後端讀取原始輸入流(推薦,零前端改動)

$json = json_decode(file_get_contents('php://input'), true);
var_dump($json['username']); // 可正常獲取

生產級統一兼容中間件(支援多端共存)

場景:API已上線服務Web/Android,新增RN端不想改動現有介面。

// 統一入口(如框架的 beforeAction / 中間件)
// 1. 識別客戶端類型(約定 Header: App: ios-appname-1.8)
if (!function_exists('apache_request_headers')) {
    $appName = $_SERVER['HTTP_APP'] ?? ''; // Nginx下大寫+HTTP_前綴
} else {
    $headers = apache_request_headers();
    $appName = $headers['App'] ?? '';
}

// 2. RN專用:JSON body 解析注入 $_POST
if ($appName === 'your-rn-app-identifier') {
    $raw = file_get_contents('php://input');
    $data = json_decode($raw, true);
    if (is_array($data)) {
        $_POST = array_merge($_POST, $data); // 合併不覆蓋
    }
}

前端 Fetch 封裝最佳實踐

const App = {
    config: { api: 'https://api.example.com', version: '1.1', debug: true },
    serialize(obj) { /* ... */ },
    random() { return Date.now() + Math.floor(Math.random()*9999); },
    
    send(url, options = {}) {
        const defaults = {
            method: 'GET',
            headers: {
                'Authorization': 'token',
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'App': 'your-rn-app-identifier', // 關鍵:後端識別用
            },
            data: { _regq: this.random() }, // 防快取
            dataType: 'json',
        };
        const opts = Object.assign({}, defaults, options);
        
        let fullUrl = this.config.api + url;
        if (opts.method === 'GET') {
            fullUrl += '?' + this.serialize(opts.data);
        }
        
        if (opts.method !== 'GET') {
            opts.body = JSON.stringify(opts.data);
        }
        
        return fetch(fullUrl, opts)
            .then(r => r.json())
            .then(res => {
                if (res.errcode === 101) return this.doLogin();
                if (res.errcode !== 0) return this.handleError(res);
                return opts.success(res, true);
            })
            .catch(err => console.warn(err));
    },
    // 使用:App.send('/api/user', { success: (res, ok) => {} })
};

關鍵點總結

  • 根因:Content-Type: application/json 導致 PHP 不自動填充 $_POST
  • 核心修復:json_decode(file_get_contents('php://input'), true)
  • 多端兼容:約定 App Header 識別客戶端,中間件統一注入 $_POST
  • 前端封裝:統一錯誤處理、Token注入、防快取、調試日誌
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved