php - 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.
解决方案
当您收到 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
如果值可能包含任何保留字符,则对正文进行百分比编码很重要。
话虽如此,还有其他一些观察结果:
如问题中提供的那样,您的代码不太有意义。您将
prepare
调用的结果(这是一个“语句”)存储到名为的变量$sql
中。(顺便说一句,因为它是一个语句,命名该变量$stmt
或者$statement
更有意义。)您稍后将其提供给query
. 但是query
期待一个 SQL 字符串,而不是返回的“语句”prepare
。相反,您应该只检查 和 的返回prepare
值。在准备、绑定、执行语句后不要调用。bind_param
execute
query
中的
s
vsi
值bind_param
与您为五个变量指定的默认值不匹配$_POST
。您可能需要仔细检查。与手头的问题没有直接关系,但我会提出一些建议。也就是说,在编写这样的 Web 服务时,我可能会建议以下建议:
设置 HTTP 状态码(例如
http_response_code(201)
插入成功、http_response_code(422)
插入失败)。我还将结果返回为 JSON(例如,使用 PHP 关联数组作为结果,然后用于
json_encode
构建由 PHP 回显的响应),而不是文本字符串。然后客户端应用程序可以轻松解析响应。我会设置
Content-Type
(例如,header("Content-Type: application/json")
),以便客户端应用程序知道如何解析响应。
一个非常小的/微妙的观察:在 PHP 中,在初始
<?php
. 在 PHP 启动之前,您不需要任何字符。它可能会导致非常微妙的问题。(希望这只是在准备问题时引入的错字,但请注意。)
推荐阅读
- java - 带有 Jaxb 和 SOAP 消息的 OpenJDK 10 中的 ClassCastException
- sql - 将三分位数加入季度 SQL(从 4 个月到 3 个月)
- python - 如何在 Python 中通知父线程作业完成
- r - reprex 忽略 system() 的输出
- bash - 我可以在 git bash 中使用命令替换吗?
- c# - 如何在一个列表中组合多个表达式
与 LINQ 一起使用? - bash - 在 shell 脚本中,将输入参数写入 json 文件
- java - Bouncycastle 无法生成私钥 - 未知 KeySpec 类型:java.security.spec.X509EncodedKeySpec
- java - 如何使用 HTML 标记为 strings.xml 文件中的字符串着色?
- python - Python 3:RuntimeError:同步对象只能通过继承在进程之间共享