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

iOS Swift+MySQL登录系统报错「数据格式错误」求助排查

Hey there! Let's break down why you're hitting that "The data couldn't be read because it is in the incorrect format" error and fix it step by step.

1. The Core Problem: Mismatched Parameters & Invalid JSON Responses

First off, your PHP script only runs its login logic if loginbutton exists in the POST request (thanks to if(isset($_POST['loginbutton']))), but neither of your Swift requests sends this parameter. That means when your app calls the endpoint, PHP returns empty data—which Swift can't parse as valid JSON, hence the error.

On top of that:

  • Your Swift formDataRequest sends parameters named cEmail and cPassword, but your PHP is looking for $_POST["email"] and $_POST["password"]—the names don't match!
  • Your jsonRequest sends data as JSON, but PHP's $_POST doesn't natively handle JSON payloads. You'd need to read from php://input to access those values, which your current PHP code doesn't do.
  • Even when PHP does run, it fails to return valid JSON for error cases (like wrong password or missing user), leaving Swift with nothing to parse.
2. Fixing the PHP Script

Let's rewrite the PHP to fix these gaps, ensure it always returns valid JSON, and add critical security fixes:

<?php
header("Content-type: application/json");
// Initialize a default error response
$response = ["erreur" => 1, "message" => "Invalid request"];

// Handle JSON payloads (for Swift's jsonRequest)
if($_SERVER['CONTENT_TYPE'] === 'application/json') {
    $_POST = json_decode(file_get_contents('php://input'), true);
}

// Check for required parameters (skip loginbutton since Swift doesn't send it)
if(isset($_POST['email']) && isset($_POST['password'])) {
    $conn = new mysqli("123", "123", "123", "123");
    if ($conn->connect_error) {
        $response["message"] = "Connection failed: " . $conn->connect_error;
        echo json_encode($response);
        exit;
    }

    // Use prepared statements to prevent SQL injection (critical security fix!)
    $email = $_POST["email"];
    $password = $_POST["password"];
    $sql = "SELECT * FROM `zusers` WHERE `cEmail` = ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("s", $email);
    $stmt->execute();
    $result = $stmt->get_result();

    if($result->num_rows == 1) {
        $row = $result->fetch_assoc();
        if(password_verify($password, $row['cPassword'])) {
            // Login success: populate response with user data
            $response["erreur"] = 0;
            $response["id"] = $row['NumUser'];
            $response["nom"] = $row['cFirstname'];
            $response["pseudo"] = $row['cEmail'];
            $response["message"] = "Login successful";
        } else {
            $response["message"] = "Incorrect password";
        }
    } else {
        $response["message"] = "User not found";
    }
    $stmt->close();
    $conn->close();
}
// Always return valid JSON, even on errors
echo json_encode($response);
?>

Key fixes here:

  • Removed the loginbutton check and replaced it with checks for the actual required parameters (email/password).
  • Added support for JSON payloads so both Swift request types work.
  • Used prepared statements to eliminate SQL injection risk.
  • Ensured every code path returns a valid JSON response (no empty outputs).
3. Fixing the Swift Code

Update your formDataRequest to send the correct parameter names, and fix the endpoint URL in your NetworkingService:

// In LoginViewController
func formDataRequest(username: String, password: String) {
    // Match PHP's expected parameter names: "email" and "password"
    let parameters = ["email": username, "password": password]
    networkingService.request(endpoint: "/login.php", parameters: parameters) { [weak self] (result) in
        switch result {
        case .success(let user):
            self?.performSegue(withIdentifier: "loginSegue", sender: user)
        case.failure(let error):
            guard let alert = self?.alertService.alert(message: error.localizedDescription) else { return }
            self?.present(alert, animated: true)
        }
    }
}

// In NetworkingService
func request(endpoint: String, parameters: [String: Any], completion: @escaping (Result<User, Error>) -> Void) {
    // Append the endpoint to the base URL (your original code used only baseUrl)
    guard let url = URL(string: baseUrl + endpoint) else {
        completion(.failure(NetworkingError.badUrl))
        return
    }
    // Rest of your code remains the same
}

Option 2: Fix the JSON Request

If you prefer using JSON, update your Login struct to match PHP's expected parameter names:

struct Login: Encodable {
    let email: String
    let password: String
}

// In LoginViewController
func jsonRequest(email: String, password: String) {
    let login = Login(email: email, password: password)
    networkingService.request(endpoint: "/login.php", loginObject: login) { [weak self] (result) in
        switch result {
        case .success(let user):
            self?.performSegue(withIdentifier: "loginSegue", sender: user)
        case.failure(let error):
            guard let alert = self?.alertService.alert(message: error.localizedDescription) else { return }
            self?.present(alert, animated: true)
        }
    }
}
4. Fix Swift JSON Decoding

Your User struct doesn't match the JSON keys returned by PHP. Add coding keys to map the PHP response to your struct (and remove cPassword—never send passwords back to the app!):

struct User: Decodable {
    let numUser: Int
    let firstName: String
    let email: String
    
    enum CodingKeys: String, CodingKey {
        case numUser = "id"
        case firstName = "nom"
        case email = "pseudo"
    }
}
5. Test First with a Tool

Before testing with Swift, use a tool like Postman or curl to send a POST request to your login endpoint. This lets you verify PHP returns valid JSON for all cases (success, wrong password, missing user) before debugging your app.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:19:37