首页 > 解决方案 > Swift not passing variables to PHP Web Service to query my SQL database

问题描述

I have a PHP Web Service that can insert a new row to my database if I hardcode the values in to the SQL query directly. But when I try to do this using variables passed to the PHP script from my Swift function it breaks down. I have add print statements to my Swift so I am confident that the values are being passed to the function correctly and the error must lie in the lines afterwards.

PHP: I have commented the SQL query line out with the hardcoded values - Carrots, but this query does work so I think PHP->SQL is working ok, but Swift->PHP is the problem.

 <?php
$servername = "localhost";
$username = "*******";
$password = "*****";
$dbname = "*******";

$product_name = $_POST['product_name'] ?? 'DefaultProduct';
$code = $_POST['code'] ?? 'DefaultCode';
$Brands = $_POST['brands'] ?? '1';
$Comp1Mat = $_POST['Comp1Mat'] ?? 'DefaultMat';
$Comp2Mat = $_POST['Comp2Mat'] ?? '1';

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

//$sql = "INSERT INTO Products (product_name, code) VALUES ('Carrots', '0135')";

$sql = $conn->prepare("INSERT INTO Products (product_name, code, brands, Comp1Mat, Comp2Mat) VALUES (?, ?, ?, ?, ?)";
$sql->bind_param("isssi", $product_name, $code, $Brands, $Comp1Mat, $Comp2Mat);
$sql->execute();
$sql->close();

if ($conn->query($sql) === TRUE) {
  echo "New record created successfully";
} else {
  echo "Error: " . $sql . "<br>" . $conn->error;
}

$conn->close();
?> 

Swift:

func addProduct(product_name: String, code: String, brands: String, Comp1Mat: String, Comp2Mat: String){
        
        print(product_name)
        print(code)
        print(brands)
        print(Comp1Mat)
        print(Comp2Mat)
        
        let insertProductURL = URL(string: "http://recyclingmadesimple.xyz/insertproduct.php")!
        var urlRequest = URLRequest(url: insertProductURL)
        urlRequest.httpMethod = "POST"
        // Set HTTP Request Headers
        urlRequest.setValue("application/json", forHTTPHeaderField: "Accept");
        urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type");
        
        let postString = "product_name=\(product_name)&code=\(code)&brands=\(brands)&Comp1Mat=\(Comp1Mat)&Comp2Mat=\(Comp2Mat)"
        urlRequest.httpBody = postString.data(using: .utf8)
        
        let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
            if error != nil {
                print("error = \(String(describing: error))")
                return
            }
            print("response - \(String(describing: response))")
            let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
            print("response string - \(String(describing: responseString))")
        }
        task.resume()

    }

Error:

response - Optional(<NSHTTPURLResponse: 0x281191600> { URL: http://recyclingmadesimple.xyz/insertproduct.php } { Status Code: 500, Headers {
    Connection =     (
        "Upgrade, close"
    );
    "Content-Length" =     (
        0
    );
    "Content-Type" =     (
        "text/html; charset=UTF-8"
    );
    Date =     (
        "Thu, 17 Jun 2021 12:38:25 GMT"
    );
    Server =     (
        Apache
    );
    Upgrade =     (
        "h2,h2c"
    );
    Vary =     (
        "User-Agent"
    );
    "X-Powered-By" =     (
        "PHP/7.4.16"
    );
} })
response string - Optional()

Many thanks.

标签: phpsqlswiftweb-services

解决方案


当您收到 500 错误时,这可能是格式错误的请求。或者它可能是 PHP 代码中的语法错误。或者两者兼而有之。

在这种情况下,很可能是 PHP 语法错误,因为在调用)结束时缺少一个。prepare但它也可能是前者(因为 Swift 代码没有对application/x-www-urlencoded请求进行百分比编码)。


当您获得 500 个代码时,请查看服务器的末尾error_log(通常在您的 PHP 文件所在的目录中)。在这种情况下,我看了看它说:

[2021 年 6 月 19 日 13:45:00 America/Boise] PHP Parse 错误:语法错误,意外的 ';',期待 ')' 在 /.../insert.php 第 103 行

这是必须修复的 PHP 中的语法错误。


话虽如此,Swift 代码中也存在问题。它正在手动构建 HTTP 请求的主体。百分之一应该对请求正文中的值进行编码。有一些库,比如Alamofire,会自动对application/x-www-urlencoded请求进行百分比编码(就是这样)。如果编写自己的 Swift 代码来构建请求,您需要手动对它们进行百分比编码,如HTTP Request in Swift with POST method中所述。

请注意,如果 (a) 您的请求包含需要百分比编码的字符(例如,空格或某些符号);并且 (b) 您没有这样做,那么这也可能导致来自 Web 服务器的 500 错误。同样,该error_log文件会告诉您出了什么问题,但是URLRequest如果值可能包含任何保留字符,则对正文进行百分比编码很重要。


话虽如此,还有其他一些观察结果:

  1. 如问题中提供的那样,您的代码不太有意义。您将prepare调用的结果(这是一个“语句”)存储到名为的变量$sql中。(顺便说一句,因为它是一个语句,命名该变量$stmt或者$statement更有意义。)您稍后将其提供给query. 但是query期待一个 SQL 字符串,而不是返回的“语句” prepare。相反,您应该只检查 和 的返回prepare值。在准备、绑定、执行语句后不要调用。bind_paramexecutequery

  2. 中的svsibind_param与您为五个变量指定的默认值不匹配$_POST。您可能需要仔细检查。

  3. 与手头的问题没有直接关系,但我会提出一些建议。也就是说,在编写这样的 Web 服务时,我可能会建议以下建议:

    • 设置 HTTP 状态码(例如http_response_code(201)插入成功、http_response_code(422)插入失败)。

    • 我还将结果返回为 JSON(例如,使用 PHP 关联数组作为结果,然后用于json_encode构建由 PHP 回显的响应),而不是文本字符串。然后客户端应用程序可以轻松解析响应。

    • 我会设置Content-Type(例如,header("Content-Type: application/json")),以便客户端应用程序知道如何解析响应。

  4. 一个非常小的/微妙的观察:在 PHP 中,在初始<?php. 在 PHP 启动之前,您不需要任何字符。它可能会导致非常微妙的问题。(希望这只是在准备问题时引入的错字,但请注意。)


推荐阅读