PHP 和 MySQL 的问题
Posted
技术标签:
【中文标题】PHP 和 MySQL 的问题【英文标题】:Problems with PHP and MySQL 【发布时间】:2013-11-25 13:22:52 【问题描述】:我在 Xcode 中工作,并且有一个 ios 应用程序,您可以输入信息,该应用程序通过 php 文件连接到数据库。上传时没有问题,姓名或电子邮件地址。但是由于某种原因,当通过UITextView
上传大量文本时,就会出现问题。当根本没有标点符号时,它就成功了。但是当有句号或问号时,它不会上传到服务器,它只会失败。但是在电子邮件字段中,句号甚至@
符号都没有问题。我不精通 PHP 或 mysql 后端的东西,所以我很困惑。这是php文件的代码:
if (isset ($_GET["firstName"]) && isset($_GET["lastName"]) && isset($_GET["emailAddress"]) && isset($_GET["deviceType"]) && isset($_GET["problemTextField"]) && isset($_GET["iosVersion"]))
$firstName = $_GET["firstName"];
$lastName = $_GET["lastName"];
$emailAddress = $_GET["emailAddress"];
$deviceType = $_GET["deviceType"];
$problemTextField = $_GET["problemTextField"];
$iosVersion = $_GET["iosVersion"];
else
$firstName = "User first name";
$lastName = "User last name";
$emailAddress = "User email address";
$deviceType = "User device type";
$problemTextField = "User problem text field";
$iosVersion = "User ios version";
$con = mysql_connect($DB_HostName,$DB_User,$DB_Pass) or die(mysql_error());
mysql_select_db($DB_Name,$con) or die(mysql_error());
$sql = "insert into $DB_Table (firstName, lastName, emailAddress, deviceType, problemTextField, iosVersion, Status, Second_Status) values('$firstName','$lastName',
'$emailAddress','$deviceType','$problemTextField','$iosVersion', 'Unanswered', 'Answered')";
$res = mysql_query($sql,$con) or die(mysql_error());
mysql_close($con);
if ($res)
echo "success";
else
echo "failed";
就像我说的,我不精通 PHP,所以请在分解我的 PHP 文件语法时表现得很好。
编辑:经过一整天的调试,我意识到如果我去掉单词之间的空格,一切都很好。是否有一个原因?我不想在所有事情之间加上加号,我知道那是不正确的。
这是我的 Xcode 代码:
NSString *strURL = [NSString stringWithFormat:@"http://www.website.com/phpFile.php?firstName=%@&lastName=%@&emailAddress=%@&deviceType=%@&problemTextField=%@&iosVersion=%@", firstName.text, lastName.text, emailAddress.text, deviceType.text, self.problemTextBox.text, iosVersion.text];
// to execute php code
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
// to receive the returend value
NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];`
【问题讨论】:
尝试在 mysql_query 之前回显你的 $sql 是什么字段?数据库中有什么类型的字段?你的表有什么编码? 不是答案,而是建议:不要使用 mysql_* 函数,它们已被弃用,很快就会消失。查看 Mysqli_* 或 PDO,两者都在 php.net mysql_* deprecated 消息中提到! :) 也可以试试 echo mysql_error($con);在 mysql_query 之后查看错误信息 使用 mysqli 或 pdo 和准备好的语句也可能解决问题! 【参考方案1】:首先,不要使用 mysql_* 函数,它们已被弃用,并将很快从 php 中删除。查看 mysqli 或 PDO 进行替换。
在与数据库通信时,检查输入很重要,因此它还不错。 您可以使用转义函数或预先准备好的语句来做到这一点。 mysqli 和 pdo 都有prepared statements。 准备好的语句将帮助您进行转义,因为您让 mysql 包装器知道它应该期望什么类型的数据,给它任何其他内容都会导致错误。
您的代码对于称为 SQL 注入 (http://en.wikipedia.org/wiki/SQL_injection) 的东西非常开放,这是一件坏事。 这可能就是您的查询在某些字符处中断的原因。 准备好的语句有助于防止这种情况发生!
请阅读 mysqli 文档,特别是 mysqli 准备好的语句:http://php.net/manual/en/book.mysqli.phphttp://php.net/manual/en/mysqli.prepare.php
我推荐 Mysqli,因为它比 PDO 更类似于 mysql api。 但是,如果您不介意学习新东西,PDO 可能会更好!
此外,正如 ddelnado 所提到的,GET 可能不是最佳选择,POST 可能更适合。
【讨论】:
我将研究在我的代码中实现这些更改。感谢您抽出宝贵时间提供帮助!【参考方案2】:几个观察:
-
你说:
但是当有句号或问号时,它不会上传到服务器,它只是失败。
您的问题假定问题出在 PHP 代码中,但听起来您在创建请求时可能没有正确地转义参数。值得注意的是,许多人错误地使用了stringByAddingPercentEscapesUsingEncoding
(这将百分比转义某些字符,但不会转义其他字符)。值得注意的是,有一些“合法”字符在 URL 中有效,但在 POST/GET 参数中无效,因此您需要指定那些也应该进行百分比转义的“合法”字符(例如 ?
、@987654325 @、+
等)在参数中。
简而言之,您确实想使用CFURLCreateStringByAddingPercentEscapes
,它允许您指定应根据RFC 3986 转义的其他字符。例如,我使用了以下NSString
类别。
@implementation NSString (URLEncode)
- (NSString *)stringForHTTPRequest
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)self,
NULL,
(CFStringRef)@":/?@!$&'()*+,;=",
kCFStringEncodingUTF8));
@end
或者使用像AFNetworking 这样的框架,它可以简化创建请求的过程并为您处理这些问题。
注意,这个 PHP 代码返回的是简单的字符串响应。相反,我建议创建 JSON 响应,这将使 Objective-C 代码更容易处理和解释响应(并报告/记录错误)。例如,如果使用 mysqli 的程序再现:
<?php
// specify that this will return JSON
header('Content-type: application/json');
// open database
$con = mysqli_connect("localhost","user","password","database");
// Check connection
if (mysqli_connect_errno())
echo json_encode(array("success" => false, "message" => mysqli_connect_error(), "sqlerrno" => mysqli_connect_errno()));
exit;
// get the parameters
$field1 = mysqli_real_escape_string($con, $_REQUEST["field1"]);
$field2 = mysqli_real_escape_string($con, $_REQUEST["field2"]);
// perform the insert
$sql = "INSERT INTO sometable (field1, field2) VALUES ('$field1', '$field2')";
if (!mysqli_query($con, $sql))
$response = array("success" => false, "message" => mysqli_error($con), "sqlerrno" => mysqli_errno($con), "sqlstate" => mysqli_sqlstate($con));
else
$response = array("success" => true);
echo json_encode($response);
mysqli_close($con);
?>
或者,如果使用面向对象的样式:
<?php
header('Content-type: application/json');
$mysqli = new mysqli("localhost", "user", "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 sometable (field1, field2) VALUES (?, ?)";
if ($stmt = $mysqli->prepare($sql))
$stmt->bind_param("ss", $_REQUEST["field1"], $_REQUEST["field2"]);
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);
?>
这样,Objective-C 应用程序可以接收响应,解析 JSON,并查看 success
以确定操作是否成功,如果错误消息则查看 message
成功。这只允许在应用程序和服务器之间进行更强大的对话。
顺便说一句,我建议您使用mysqli_real_escape_string
或手动将参数绑定到准备好的语句,以防止 SQL 注入攻击或 SQL 中未转义的字符串引起的意外错误。
我还建议您创建一个 POST
请求,而不是一个允许更大值的 GET
请求。
【讨论】:
我目前不在电脑旁,所以我无法从 Xcode 获取我的确切代码。但是我正在做的是按下按钮将信息“提交”到数据库中,我通过 URLstring 获取 php 文件,然后使用 nsdata 语句执行,然后获取数据语句来表示成功与否。这不是正确的方法吗?还是应该将您的代码添加到我的方法中?回到家后,我将使用我的代码对其进行编辑。 以及我之前的说法。我真的要深入研究 AFNetworking 框架,它可能会使这变得更容易,并为我提供更强大的程序。 @user1813278 您可能应该创建一个POST
请求,它不只是将参数添加到URL(就像您可以使用GET
请求一样),而是添加@987654339 @ 请求正文的参数。如果你愿意,你可以自己做,但需要创建一个NSMutableURLRequest
,使用setHTTPMethod
到POST
,使用setHTTPBody
和POST
变量,设置一些其他标头值等。AFNetworking 完成所有这对你来说(以及正确地转义值和解析 JSON 响应),所以它更容易一些。祝你好运!
这是我的 Xcode 代码NSString *strURL = [NSString stringWithFormat:@"http://www.website.com/phpFile.php?firstName=%@&lastName=%@&emailAddress=%@&deviceType=%@&problemTextField=%@&iosVersion=%@", firstName.text, lastName.text, emailAddress.text, deviceType.text, self.problemTextBox.text, iosVersion.text]; // to execute php code NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]]; // to receive the returend value NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
除此之外,我注意到,经过一整天的调试,如果我从文本中删除空格,一切都很好。举个例子,我知道这是不受欢迎的,但如果你在每个地方都加上一个空格,那就没有错误了。这是有原因的吗?【参考方案3】:
使用 mysql_real_escape_string 之类的
$firstName = mysql_real_escape_string($_GET["firstName"]);
在所有获取值之前
谢谢
【讨论】:
【参考方案4】:您不应该使用 $_GET 超全局变量。 Get 方法对数据的大小有限制,而 $_POST 超全局没有限制。所以你的代码应该是这样的。\
if (isset ($_POST["firstName"]) && isset($_POST["lastName"]) && isset($_POST["emailAddress"]) && isset($_POST["deviceType"]) && isset($_POST["problemTextField"]) && isset($_POST["iosVersion"]))
$firstName = $_POST["firstName"];
$lastName = $_POST["lastName"];
$emailAddress = $_POST["emailAddress"];
$deviceType = $_POST["deviceType"];
$problemTextField = $_POST["problemTextField"];
$iosVersion = $_POST["iosVersion"];
我不知道您使用什么表单来提交此表单,但该表单的方法也需要发布。此外,您应该始终在将变量插入数据库之前对其进行转义,以免发生 sql 注入。
【讨论】:
谢谢,刚刚解决了。以上是关于PHP 和 MySQL 的问题的主要内容,如果未能解决你的问题,请参考以下文章
阅读 Robin Nixon 的学习 PHP、MySQL 和 JavaScript 时提出的问题 RE:清理输入 PHP [重复]