You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+PHP登录功能POST请求无法接收参数问题排查

React + PHP登录功能PHP端无法接收请求参数的问题解决

问题描述

  • 登录功能与注册功能实现逻辑一致,但PHP端始终无法接收请求参数
  • Chrome浏览器中请求显示被重定向,Firefox浏览器中因请求数据为空抛出错误
  • 注册功能中通过file_get_contents("php://input", true)可正常获取请求数据,但登录功能中该方法返回空值

相关代码

Fetch钩子函数

import React, { useEffect, useState } from 'react'

function useFetch(url, options) {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(null);
    const [error, setError] = useState(null);
    useEffect(() => {
        if(!url) return;
        setLoading(true);
        setTimeout(() => {
            (async function fetchData() {
                try {
                    const response = await fetch(url, options);
                    if(!response.ok) throw new Error();
                    const data = await response.json();
                    setData(data);
                    setLoading(false)
                } catch(e) {
                    setLoading(false)
                    setError(e.message);
                }
            })()
        }, 3000);;
    }, [url])
    return [data, loading, error];
}

export default useFetch

登录组件

import React, { useState } from 'react'
import classes from '../../assets/styles/Main.module.css'
import useFetch from '../../hooks/useFetch';
function Login() {
    const [userInputs, setUserInputs] = useState({
        "username": "nadim",
        "email": "nadim.aa@hotmail.com",
        })
    const [url, setUrl] = useState(null);
    const [data, loading, error] = useFetch(url,  {
        method: "POST",
        body: JSON.stringify(userInputs),
        mode: "no-cors",
    });

    const submitHandler = () => {
        setUrl("http://localhost/whatsinit/api/user");
    }
    console.log(data, loading, error);
    return (
        <div className={classes.login}>
            <h2>Login to your account</h2>
            <input className={classes.login_username} type='text' placeholder='Username or email'/>
            <input className={classes.singup_password} type='password' placeholder='Password'/>
            <button onClick={submitHandler} className={classes.register_button}>login</button>
        </div>
    )
}

export default Login

PHP代码

<?php 
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST");
header("Access-Control-Allow-Headers: Content-Type");
include_once '../../config/Database.php';

class User {
    private $table = 'users';
    private $connection;
    private $username;
    public function __construct($connection, $user_inputs) {
        $this->connection = $connection;
        if(!is_null($user_inputs)) {
            $this->username = $user_inputs['username'];
            $this->email = $user_inputs['email'];
        }
    }
    public function readUser() {
        try {
            $command = "SELECT * FROM $this->table WHERE (username = ? OR email = ?);";
            $stmt = $this->connection->stmt_init();
            $stmt->prepare($command);
            $stmt->bind_param("ss", $this->username, $this->email);
            if(!$stmt->execute()) {
                throw new Exception("Could not get user");
            }
            $response = $stmt->get_result();
            return $response;
        } catch (\Throwable $th) {
            echo json_encode($th->getMessage());
        }
        $this->connection->close();
    }
}

$database = new Database();
$connection = $database->connect();
$user = new User($connection, json_decode(file_get_contents("php://input", true)));

try {
    $result = $user->readUser();
    $nums = $result->num_rows;
    $json_items = array();
    if($nums) {
        while($row = $result->fetch_assoc()) {
            extract($row);
            array_push($json_items, $row);
        }
    } else {
        throw new Exception("Not Registered!");
    }
    echo json_encode($json_items);
} catch (\Throwable $th) {
    echo json_encode($th->getMessage());
    exit();
}
?>

解决方案

1. 移除mode: "no-cors"配置

no-cors模式会限制浏览器请求行为,无法发送Content-Type: application/json头,也无法读取响应内容,直接导致PHP端无法解析JSON请求体。修改登录组件的fetch配置:

const [data, loading, error] = useFetch(url,  {
    method: "POST",
    body: JSON.stringify(userInputs),
    headers: {
        "Content-Type": "application/json" // 显式指定请求格式
    }
    // 移除 mode: "no-cors"
});

2. 修复useFetch钩子的依赖与延迟问题

  • 原钩子仅监听url变化,options参数更新时不会触发重新请求,需将options加入依赖数组
  • 不必要的setTimeout会延迟请求,且可能导致状态更新异常,直接移除

修改后的useFetch钩子:

import React, { useEffect, useState } from 'react'

function useFetch(url, options) {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(null);
    const [error, setError] = useState(null);
    useEffect(() => {
        if(!url) return;
        setLoading(true);
        (async function fetchData() {
            try {
                const response = await fetch(url, options);
                if(!response.ok) throw new Error(`HTTP错误!状态码: ${response.status}`);
                const data = await response.json();
                setData(data);
                setLoading(false)
            } catch(e) {
                setLoading(false)
                setError(e.message);
            }
        })()
    }, [url, options]) // 添加options到依赖数组
    return [data, loading, error];
}

export default useFetch

3. 修复PHP的JSON解析逻辑

json_decode(file_get_contents("php://input", true))默认返回对象,而User构造函数使用数组方式访问属性,需将第二个参数设为true转为关联数组:

$user = new User($connection, json_decode(file_get_contents("php://input", true), true));

4. 绑定登录输入框与状态

原登录组件的输入框未与userInputs绑定,提交的是固定测试数据,添加onChange事件同步输入值:

function Login() {
    const [userInputs, setUserInputs] = useState({
        "username": "",
        "email": "",
        "password": "" // 补充password字段
    })
    // ...其余代码

    return (
        <div className={classes.login}>
            <h2>Login to your account</h2>
            <input 
                className={classes.login_username} 
                type='text' 
                placeholder='Username or email'
                value={userInputs.username}
                onChange={(e) => setUserInputs(prev => ({...prev, username: e.target.value}))}
            />
            <input 
                className={classes.singup_password} 
                type='password' 
                placeholder='Password'
                value={userInputs.password}
                onChange={(e) => setUserInputs(prev => ({...prev, password: e.target.value}))}
            />
            <button onClick={submitHandler} className={classes.register_button}>login</button>
        </div>
    )
}

5. 完善PHP的CORS预检请求处理

添加OPTIONS请求的处理逻辑,避免浏览器预检请求报错:

// 处理OPTIONS预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Methods: GET, POST");
    header("Access-Control-Allow-Headers: Content-Type");
    exit();
}

// 原有的CORS头与业务逻辑
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST");
header("Access-Control-Allow-Headers: Content-Type");
include_once '../../config/Database.php';
// ...其余代码

内容的提问来源于stack exchange,提问作者Nadim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 06:37:02