查询通过phpMyAdmin工作,但不能通过从viewController调用的PHP脚本工作

我有一个tableViewController呈现按名称sorting的地方列表! 这个列表是使用查询从我的MySQL数据库中检索的

从Castle ORDER BY Name中selectIDUser

但我的目标是根据userLocation按位置sorting。 所以,数据库中的任何地方都有“纬度”和“经度”字段。

在我的tableViewController我做到这一点:

NSString *IDString = @"SELECT ID FROM Castle ORDER BY Name ASC"; NSMutableString *strURL = [NSMutableString stringWithFormat:@"http://localhost/myApp/fieldsRequest.php?query=%@",query]; [strURL setString:[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]]; NSError* error; NSDictionary* json = [NSJSONSerialization JSONObjectWithData:dataURL options:kNilOptions error:&error]; NSMutableArray *results = [[NSMutableArray alloc] init]; int numRow = 0; for (NSArray *arrow in json) { [results addObjectsFromArray:arrow]; numRow++; } return results; 

被称为脚本的PHP:

 <?php require 'mycredentials.php'; $resultCredentials = sdbmyCredentials(); if ($resultCredentials == YES) { $arr = array(); $query = $_GET[query]; $results = mysql_query($query) or die ("Unhandled exception: " . mysql_error()); // Add the rows to the array while($obj = mysql_fetch_row($results)) { $arr[] = $obj; } echo json_encode($arr); } ?> 

它完美的作品,我检索的名字顺序列表名称。 相反,当我这样做:

 _IDString = [NSString stringWithFormat:@"SELECT ID FROM Castle ORDER BY (POW((longitude-%f),2) + POW((latitude-%f),2))", longitude,latitude]; NSMutableString *strURL = [NSMutableString stringWithFormat:@"http://localhost/myApp/fieldsRequest.php?query=%@",query]; [strURL setString:[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]]; NSError* error; NSDictionary* json = [NSJSONSerialization JSONObjectWithData:dataURL options:kNilOptions error:&error]; NSMutableArray *results = [[NSMutableArray alloc] init]; int numRow = 0; for (NSArray *arrow in json) { [results addObjectsFromArray:arrow]; numRow++; } return results; 

我在string中给出的纬度和经度分别是40.535568和16.503588在phpMyAdmin中,如果我运行sql命令:

SELECT ID FROM Castle ORDER BY(POW((longitude-16.503588),2)+ POW((latitude-40.535568),2))

它完美的作品,它给了我的结果。 但是,如果我像之前写的那样通过代码执行它,它不会产生结果,但会出错:

未处理的exception:您的SQL语法中有错误; 检查与您的MySQL服务器版本相对应的手册,以便在第1行的“POW((latitude-40.535568),2))”附近使用正确的语法

这是string地址:

 http://localhost/myApp/fieldsRequest.php?query=SELECT%20ID%20FROM%20Castle%20ORDER%20BY%20(POW((longitude-16.503588),2)+POW((latitude-40.535568),2)) 

问题是stringByAddingPercentEscapesUsingEncoding只能转义那些在URL中无效的字符。 但是在一般的URL(例如&+ )中有一些允许使用的字符,但是在URL参数(例如& delimits参数, +转换为空格字符)中没有问题。

因此,不是stringByAddingPercentEscapesUsingEncoding ,而是想要一个百分比转义的方法,不仅是那些在URL中无效的字符,还有那些在一般的URL中可能具有特殊含义的字符,但在参数中是有问题的。 在这种情况下,您希望百分比转义出现在SQL中的+

最简单的方法是使用CFURLCreateStringByAddingPercentEscapes ,而不是stringByAddingPercentEscapesUsingEncoding

 - (NSString *)percentEscapeURLParameter:(NSString *)string { return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, (CFStringRef)@":/?@!$&'()*+,;=", kCFStringEncodingUTF8)); } 

顺便说一下,你应该把参数转换成URL,而不是URL本身。

 NSString *sql = [NSString stringWithFormat:@"SELECT ID FROM Castle ORDER BY (POW((longitude-%f),2) + POW((latitude-%f),2))", longitude, latitude]; NSString *percentEscapedSQL = [self percentEscapeURLParameter:sql]; NSString *strURL = [NSString stringWithFormat:@"http://localhost/myApp/fieldsRequest.php?query=%@", percentEscapedSQL]; // don't percent-escape the full URL // // [strURL setString:[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 

顺便说一句,我衷心地劝阻你传递URL中的SQLstring。 这是一个严重的安全风险。 您应该只传递参数(例如经度和纬度),并让PHPvalidation这些参数,然后构buildSQL本身。