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,使用setHTTPMethodPOST,使用setHTTPBodyPOST 变量,设置一些其他标头值等。AFNetworking 完成所有这对你来说(以及正确地转义值和解析 JSON 响应),所以它更容易一些。祝你好运! 这是我的 Xcode 代码NSString *strURL = [NSString stringWithFormat:@"http://www.website.com/phpFile.php?firstName=%@&amp;lastName=%@&amp;emailAddress=%@&amp;deviceType=%@&amp;problemTextField=%@&amp;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 的问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 PHP 和 MySQL 显示日文字符的问题

PHP和MYSQL的编码问题

PHP/MYSQL 数组存储和检索问题

PHP 和 MySQL 的问题

动态网站安全问题(PHP+MySQL)

阅读 Robin Nixon 的学习 PHP、MySQL 和 JavaScript 时提出的问题 RE:清理输入 PHP [重复]