iPhone中的RESTful Web服务:未插入数据库的数据

时间:2011-07-02 04:17:07

标签: php iphone mysql objective-c web-services

我开始使用MAMP附带的“形状”Web服务进行教程。现在我正在尝试为自己重新创建一项服务。我现在一直在寻找解决方案或如何在过去5个小时内调试问题。我的强项不是PHP,所以我不确定如何设置调试或某种方式来打印URL响应。非常感谢任何人的帮助。

Objective-C代码:

NSString* serviceRootUrlString = @"http://localhost:8888/answers/Answers/";
NSURL* answerService = [NSURL URLWithString:serviceRootUrlString];
_database = [[Database alloc] initWithServiceUrl:answerService];

- (void)nextQuestionWithAnswer:(NSString *)answer andComment:(NSString *)comment
{
    NSString* deviceId = [[UIDevice currentDevice] uniqueIdentifier];
    NSData* deviceIdAsData = [deviceId dataUsingEncoding:NSUTF8StringEncoding];
    NSString* deviceHash = [Database MD5Hash:deviceIdAsData];

    NSMutableDictionary* answerDictionary = [NSMutableDictionary dictionary];
    [answerDictionary setObject:deviceHash forKey:@"SetId"];
    [answerDictionary setObject:[NSNumber numberWithInt:(_currentQuestionNumber + 1)] forKey:@"QuestionId"];
    [answerDictionary setObject:answer forKey:@"Answer"];
    [answerDictionary setObject:comment forKey:@"Comment"];

    [_database insertRecordWithDictionary:answerDictionary];

    [self nextQuestion];
}

- (BOOL)insertRecordWithDictionary:(NSDictionary *)recordDictionary
{
    NSData* recordPropertyListData = [NSPropertyListSerialization dataFromPropertyList:recordDictionary format:NSPropertyListXMLFormat_v1_0 errorDescription:nil];

    NSMutableURLRequest* urlRequest = [NSMutableURLRequest requestWithURL:_serviceUrl];
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:recordPropertyListData];

    NSURLResponse* response = nil;
    NSError* error = nil;

    NSData* responseData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];

    id propertyList = [NSPropertyListSerialization propertyListWithData:responseData options:NSPropertyListImmutable format:nil error:nil];

    NSDictionary* responseDictionary = (NSDictionary*)propertyList;

    NSLog(@"New Record result: %@", responseDictionary);

    if (error == nil)
    {
        return YES;
    }
    else
    {
        NSLog(@"Database Error: %@", [error description]);

        return NO;
    }
}

PHP代码:

<?php
require_once 'CFPropertyList/CFPropertyList.php';

// connect to database
$connection = mysql_connect("localhost:8889","root","root");
if (!$connection)
    die("Could not connect: " . mysql_error());

// Database layout
$databaseName = "answers";
$surveyAnswersTableName = "Answers";
$surveyAnswersArrayName = "Answers";
$answerId = "Id";
$answerTimeStamp = "TimeStamp";
$answerSetId = "SetId";
$answerQuestionId = "QuestionId";
$answerAnswer = "Answer";
$answerComment = "Comment";

// Determine the requested resource, stripping empty resource elements and the base name
$base = "answers";
$resourceKeys = array_merge(array_diff(explode("/", $_SERVER[REQUEST_URI]), array("", $base)));

// Detect usage of the old setup
if (count($resourceKeys) == 0)
    die("Specify a table that contains your shapes. Ex: http://the_host_name:8888/answers/your_user_name/");

// Use the first resource key as the table name, then strip it away
$surveyAnswersTableName = $resourceKeys[0];
$resourceKeys = array_merge(array_diff($resourceKeys, array($surveyAnswersTableName)));

// Check for the database. Create the database and populate it if it does not exist
$databaseExists = mysql_select_db($databaseName, $connection);
if (!$databaseExists)
{
    // Create and select the ozzie database
    mysql_query("CREATE DATABASE $databaseName",$connection);
    $databaseExists = mysql_select_db($databaseName, $connection);
    if (!$databaseExists)
        die("Could not create database $databaseName: " . mysql_error());
}

// Check for the requested answers table
$sql = "SHOW TABLES LIKE '$surveyAnswersTableName'"; 
mysql_query($sql, $connection);
$row = mysql_fetch_array($result);
print($row);

// Create it if it does not exist
if ($row == FALSE)
{
    // Create the table that holds the answers
    $sql = "CREATE TABLE $surveyAnswersTableName 
    (
        $answerId int NOT NULL AUTO_INCREMENT PRIMARY KEY,
        $answerTimeStamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        $answerSetId text,
        $answerQuestionId int, 
        $answerAnswer text,
        $answerComment text
    )";

    mysql_query($sql, $connection);
}

if ($_SERVER[REQUEST_METHOD] == "POST")
{
    // Insert or append shape specified in POST to the database
    if (count($resourceKeys) == 0)
    {
        // Load the posted plist into a property list object
        // HACK: Save post data to file to load into plist. Should be able to load directly from php://input, but won't...
        $postdata = file_get_contents("php://input");
        $fileName = dirname(__FILE__) . "/tmp.php";
        $file = fopen($fileName, 'w') or die("Cannot open file");
        fwrite($file, $postdata);
        fclose($file);
        $postPlist = new CFPropertyList($fileName);
        unlink($fileName);

        // Unpack data for answer
        // TODO: Verify data
        $answerDictionary = $postPlist->getValue(true);
        $setId = $answerDictionary->get($answerSetId);
        $questionId = $answerDictionary->get($answerQuestionId);
        $answer = $answerDictionary->get($answerAnswer);
        $comment = $answerDictionary->get($answerComment);

        // Insert answer into database
        $sql = "INSERT INTO $surveyAnswersTableName
        (
            $answerSetId,
            $answerQuestionId, 
            $answerAnswer, 
            $answerComment
        ) 
        VALUES 
        (
            '$setId',
            '$questionId',
            '$answer',
            '$comment'
        )";

        mysql_query($sql,$connection);

        print($sql);

        // Package result into outer dictionary
        // TODO: Call method instead

        $resultDictionary = new CFDictionary();
        $resultDictionary->add($surveyAnswersArrayName, new CFString("Answer inserted."));

        // Package outer dictionary into a property list and transmit
        $resultPlist = new CFPropertyList();
        $resultPlist->add($resultDictionary);
        header("Content-type: text/xml");
        print($resultPlist->toXML(true));
    }
    else if (count($resourceKeys) >= 1)
    {
        // Load the posted plist into a property list object
        // HACK: Save post data to file to load into plist. Should be able to load directly from php://input, but won't...
        $postdata = file_get_contents("php://input");
        $fileName = dirname(__FILE__) . "/tmp.php";
        $file = fopen($fileName, 'w') or die("Cannot open file");
        fwrite($file, $postdata);
        fclose($file);
        $postPlist = new CFPropertyList($fileName);
        unlink($fileName);

        // Unpack data for shape
        // TODO: Verify data
        $answerDictionary = $postPlist->getValue(true);
        $setId = $answerDictionary->get($answerSetId);
        $questionId = $answerDictionary->get($answerQuestionId);
        $answer = $answerDictionary->get($answerAnswer);
        $comment = $answerDictionary->get($answerComment);

        // Determine requested shape
        $requestedAnswerSetId = $resourceKeys[0];

        // Query to re-number shapes
        $sql = "UPDATE $surveyAnswersTableName SET $answerId = $answerId + 1 WHERE $answerId >= $requestedAnswerId";
        print($sql);
        $result = mysql_query($sql);

        // Insert shape into database
        $sql = "INSERT INTO $surveyAnswersTableName
        (
            $answerSetId,
            $answerQuestionId, 
            $answerAnswer, 
            $answerComment
        ) 
        VALUES 
        (
            '$setId',
            '$questionId',
            '$answer',
            '$comment'
        )";

        mysql_query($sql,$connection);

        print($sql);

        // Package result into outer dictionary
        // TODO: Call method instead
        // TODO: Verify that add completed successfully
        $resultDictionary = new CFDictionary();
        $resultDictionary->add($surveyAnswersArrayName, new CFString("Answer inserted."));

        // Package outer dictionary into a property list and transmit
        $resultPlist = new CFPropertyList();
        $resultPlist->add($resultDictionary);
        header("Content-type: text/xml");
        print($resultPlist->toXML(true));
    }
    else 
        die("Invalid request");
}

?>

我知道我要求有人分析这些代码,但我们将非常感激。

1 个答案:

答案 0 :(得分:2)

使用iOS和XCode进行打印响应:

NSData* responseData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
NSLog(@"Reponse: %@", [[[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding] autorelease]);

为了检查没有iOS的php响应,只需创建包含输入的HTML表单的某个html文件。这些输入必须具有与recordDictionary变量相同的键和值。表单操作应该类似于serviceRootUrlString变量,方法POST。

See this tutorial for more information about HTML forms