如何使用 objective-c 将 JSON 数据发布到 PHP 数据库


How to post JSON data to PHP database using objective-c?

我在将数据发送到我的在线数据库时遇到问题。当我检查数据库时,似乎没有任何发布。我对收到的响应执行了 NSLog,它是空白的。

以下是.php:

<?php
        $db_host="someurl.com";
        $db_username="some_user"; 
        $db_pass="some_passwd";
        $db_name="some_db";
        $conn = mysql_connect($db_host, $db_username, $db_pass) or die ("Could not connect to 
                                                                        MySQL"); 
        mysql_select_db("$db_name") or die ("No database");
        // array for JSON response
        $json = $_SERVER['HTTP_JSON'];
        $data = json_decode($json);
        $some1_id = $data->some1_id;
        $imei = $data->imei;
        //does the imei exist?
        $result = mysql_query("SELECT * FROM usr_go WHERE imei = '".$imei."'"); 
        if (mysql_num_rows($result) == 0){
            if(isset($some1_id))
                $result = mysql_query("INSERT INTO usr_go(some1_id, imei) VALUES('".$some1_id."','".$imei."')");
        }
        else{
            if(isset($some1_id))
                $result = mysql_query("UPDATE usr_go SET some1_id = '".$some1_id."' WHERE imei = '". $imei ." AND some1_id IS NULL ");
        }
        mysql_close($conn);
        header('Content-type: application/json');
        $response = $result;
        echo json_encode($response);
?>

但是,如果我将$response硬编码为某个字符串值,并且 NSLog 接收到的响应,它将接收相应的字符串值。

这是我的代码:

NSDictionary *dict = @{@"some1_id" : [NSNumber numberWithInt:self.cellIndex]};
    NSError *error = nil;
    NSData *json = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
    if (json)
    {
        NSURL *url = [NSURL URLWithString:@"someurl.com"];
        NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
        [req setHTTPMethod:@"POST"];
        [req setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [req setHTTPBody:json];
        NSURLResponse *res = nil;
        NSData *ret = [NSURLConnection sendSynchronousRequest:req returningResponse:&res error:&error];
        NSString *resString = [[NSString alloc] initWithData:ret encoding:NSUTF8StringEncoding];
        NSLog(@"response String: %@",resString);

        NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
        NSLog(@"JSON Output: %@", jsonString);
    }
    else
    {
        NSLog(@"Unable to serialize the data %@: %@", dictionary, error);
    }

是无法插入IMEI的事实,这就是为什么它没有发布,还是其他一些问题?

感谢您的帮助。

几个观察结果:

  1. 您应该使用msqli接口,而不是已弃用的mysql接口。

  2. 你永远不应该接受输入,只在SQL语句中使用它。使用mysqli_real_escape_string或绑定值(如下所示)。这对于确保您不容易受到 SQL 注入攻击至关重要。它还可以保护您免受插入的值恰好包含保留字符时可能出现的无辜错误的影响。

  3. 与其试图json_encode结果的结果mysqli_query不如构建一个更有意义的关联数组。例如,您可以检查mysqli调用的结果,如果成功则返回一个 JSON,并在失败时返回另一个 JSON。我可能会建议让失败再现返回错误消息。

  4. 您应该在Web浏览器中测试PHP,或者使用Charles之类的设备对其进行测试。确保在客户端代码走得太远之前,获取预期的 JSON。底线,看看你是否可以相互隔离地测试客户端代码和服务器代码(或者一开始尽可能保持简单)。

  5. 我不熟悉这个$_SERVER['HTTP_JSON'];结构。如果这对您有用,那就太好了,但它在我的服务器上不起作用。我历来做过fopen php://input如下图所示。

例如,这是一个不同的数据库/表,但它可以说明PHP代码可能是什么样子的:

// read JSON input
$handle = fopen("php://input", "rb");
$raw_post_data = '';
while (!feof($handle)) {
    $raw_post_data .= fread($handle, 8192);
}
fclose($handle);
$request_data = json_decode($raw_post_data, true);
// prepare header for reply
header("Content-Type: application/json");
// open database
$mysqli = new mysqli($host, $userid, $password, $database);
// check connection 
if ($mysqli->connect_errno) {
    echo json_encode(array("success" => false, "message" => $mysqli->connect_error, "sqlerrno" => $mysqli->connect_errno));
    exit();
}
// perform the insert
$sql = "INSERT INTO locations (message, device, longitude, latitude) VALUES (?, ?, ?, ?)";
if ($stmt = $mysqli->prepare($sql)) {
    $stmt->bind_param("ssdd", $request_data["message"], $request_data["device"], $request_data["latitude"], $request_data["longitude"]);
    if (!$stmt->execute())
        $response = array("success" => false, "message" => $mysqli->error, "sqlerrno" => $mysqli->errno, "sqlstate" => $mysqli->sqlstate);
    else
        $response = array("success" => true);
    $stmt->close();
} else {
    $response = array("success" => false, "message" => $mysqli->error, "sqlerrno" => $mysqli->errno, "sqlstate" => $mysqli->sqlstate);
}
$mysqli->close();
echo json_encode($response);

显然,请为您的表更改此设置,但它说明了上述一些概念。我通常会添加更多的错误检查(例如请求的Content-Type,测试以确保在我尝试使用变量之前设置变量等),但您可能明白了。


在客户端,还有一些小观察:

  1. 最严重的问题是使用sendSynchronousRequest。请改用sendAsynchronousRequest(或无数其他异步技术中的任何一种)。切勿从主线程发出同步请求。

  2. 解析响应时,resString将包含原始 JSON。我不知道您在构建jsonString时引用的jsonData变量是什么,但这看起来不正确。

    如果要解析响应,它将是:

    NSError *parseError;
    NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
    

    顺便说一下,上面假设你在响应中返回一个 JSON 字典,就像我在示例中所做的那样,而不是你的原始 JSON 所做的。