7

So I've looked through an endless number of like problems but none of them answered what I was looking for or answered it in a complete manner so hopefully you all can help me out.

I need to pass an array of restaurantID's from iOS to a PHP file using POST or anyway that would work well. I know about ASIHTTPRequest but I'm looking for something built in and it has been abandon by the developer. And lastly, I don't want to pass them through the URL because I don't know how many entries there will be.

So here's what I got so far.

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:theURL]];

[request setHTTPMethod:@"POST"];

NSMutableDictionary *jsonDict = [[NSMutableDictionary alloc] init];
[jsonDict setValue:restaurants forKey:@"restIDs"];
NSLog(@"JSON Dict: %@",jsonDict);//Checking my array here


NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict options:kNilOptions error:nil];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"JSON String: %@",jsonString); //Checking my jsonString here...

[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

[request setValue:@"json" forHTTPHeaderField:@"Data-Type"];
[request setValue:[NSString stringWithFormat:@"%d", [jsonData length]] forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody: jsonData];
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSLog(@"Return DATA contains: %@", [NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableContainers error:nil]);
NSArray *restMenuCount = [NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableContainers error:nil];

So, from this end, I've checked everything and it all looks good, but from the PHP end it doesn't even pick it up.

Here's what my PHP file looks like:

$restIDs = $_POST['restIDs'];
echo $restIDs; //Checking to see if it even has anything......but nothing there
for ($i = 0; $i < $restIDs.count; $i++) {
    $query = "SELECT * FROM `MenuItems` WHERE rest_id = '$restID'";
    $result = mysqli_query($connect, $query);
    $number = mysqli_num_rows($result);
    $menuNumber[$i] = $number;
}

echo json_encode($menuNumber);

So finally, what am I doing wrong? Why am I not receiving anything on my PHP end. And most of all, can someone explain to me how to send array's via a POST. Because I feel like that's my real problem here, I don't understand it enough to fix the problem myself. I don't understand how you can put everything in from the iOS side and pick it up on the PHP side.

I hope all of this was clear enough, thanks in advance.

EDIT:
I tried passing the array as a string through the URL then exploding it, luckily it worked...but I'm just under the URL limit, so I'd still like to figure out another solution. At least, now I know the rest of my code was working as expected.

WiseOlMan
  • 926
  • 2
  • 11
  • 26

2 Answers2

8

You seem to have a basic misunderstanding of how the $_POST variable is filled in. Specifying the document type as JSON and throwing the JSON string in as the post body will not auto-populate this array. The body has to be in a specific format. Usually, this means url-encoded pairs, eg a=1&b=2&c=2&d=%2fg+y etc. This somewhat limits the kind of data you can send. In particular, an arbitrary JSON object is not possible in this sense, if you want it to show up in the $_POST variable automatically. There are a few options from here:

Option one: Rather than using $_POST, use the post body directly. Use fopen("php://input") and parse that using a PHP JSON parser:

$input = file_get_contents("php://input");
$obj = json_decode($input,true);
$restIDs = $obj['restIDs'];

If you went this route you need not create an object with a field named restIDs though. You can instead simply serialize the array and use $obj as $restIDs

Option two, assuming your objects in restIDs are simply strings, instead of passing the data in as a JSON object, format the body as intended for PHP use:

NSMutableString *bodyStr = [NSMutableString string];
for (NSString *restID in restaurants) {
    [bodyStr appendFormat:@"restIDs[]=%@&",[restID stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
NSData *body = [bodyStr dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody: body];

Now you should be able to access it using $_POST['restIDs'] as you would expect.

Ed Marty
  • 39,590
  • 19
  • 103
  • 156
  • Hi Ed, I tried the second option, but didn't completely understand how to implement it since nothing come out on the other side. How will the bodyStr be constructed into an array inside $_POST? Also, for the first option, I kept everything as it was for my question, and added your three lines to my PHP code, then echo'd $obj['restIDs'] and $obj and nothing came out. What could I be doing wrong? Is my POST set up wrong on the iOS side? – WiseOlMan Dec 03 '12 at 17:29
  • From what I can see, everything looks about right. Other than you have an echo statement at the top of the php script, which will mangle your output when you try to parse it as a JSON back on the iOS side. I would suggest lots of `NSLog` statements in the Objective-C code and lots of `var_dump` statements on the php side to track things down. In particular, try `var_dump(file_get_contents("php://input"));` – Ed Marty Dec 04 '12 at 14:49
  • Okay, I'll post back when I've tracked down the culprit, thanks! – WiseOlMan Dec 04 '12 at 17:49
1

You are passing the array wrong. First you placed it in a JSON string and then you didn't put the JSON String in the post variables but as the body of the HTML message. If you are going to use JSON to transfer data to PHP via a POST message you need to set it as a post variable. Then in PHP, you read the variable and decode the json to get your original variables. Here's an example of how I did it.

Sorry I originally pasted the Java code here. This might make more sense.

-(void) setPath: (NSString *) input
{
    Path=input;
}

-(void) run
{
    NSDictionary* jsonDictionary=[NSDictionary dictionaryWithObject: data1 forKey:@"data"];
    NSString* jsonString = [jsonDictionary JSONRepresentation];
    AFHTTPClient *httpClient=[[AFHTTPClient alloc] initWithBaseURL:url];
    NSDictionary *params =[NSDictionary dictionaryWithObjectsAndKeys:
                           apps,@"app",
                           jsonString,@"smpdata",nil];
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:Path parameters:params];

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

    NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

    if (error) {
        NSLog(@"Error: %@",error);
    }
    else {
        id JSON = AFJSONDecode(data, &error);
        NSArray *dataarray=[JSON valueForKey:@"Data"];
        status= [NSString stringWithFormat:@"%@",[JSON valueForKeyPath:@"Status"]];
        NSLog(@"%@",status);
        returndata= dataarray;

    }
}

-(NSArray *) returndata {
    return returndata;
}

-(NSString *) status {
    return status;
}

@end

PHP

<?
$jsondata=$_POST['smpdata'];
$data = json_decode($jsondata);
?>
Codeguy007
  • 891
  • 1
  • 12
  • 32
  • Hi Codeguy, the problem with this approach is that I don't know how many variables I will have ahead of time, so name/value pairs won't do the trick. Is there a way I could decode the json into an array that I can iterate through? How would I do that? Also, you mentioned that I'm passing my JSON data wrong. How would I pass it as a post variable? And then how would I grab it on the PHP side? Thanks. – WiseOlMan Dec 03 '12 at 17:35
  • We handled that by using an array. The array could contain as many rows as the number of variables. We sometimes we just throw the variables into a csv string and pass that too in the JSON string. Neither the array or csv string have defined rows or columns so they can be variable. There might be a better way but passing the csv string was decided on long before using JSON. – Codeguy007 Dec 03 '12 at 20:43