PHP MySQL查询在某些情况下失败


PHP MySQL query failing in some cases?

我有一个PHP脚本,它接收将客户端输入数据库的post请求,大多数时候它都能工作,但在某些情况下,如果客户端的名字中有特殊字符,它就会失败。更奇怪的是,如果我试着在PHPMyAdmin中手动运行查询,它会正常工作,我使用的PHP代码如下:

$mysql = new mysqli("***", "****", "****", "****");
mysqli_set_charset($mysql,"utf8mb4");
if (isset($_POST["name"])) {
$name = $mysql->real_escape_string($_POST["name"]);
} else {
mysqli_close($mysql);
die("Name not set");
}
$query = sprintf ("INSERT INTO `que` (`name`, `ip`, `steamid`, `serverip`) VALUES ('%s', '%s', '%s', '%s')", $name, $clientip, $steamid, $serverip.":".$serverport);
if(!$mysql->query($query)) {
    mysqli_close($mysql);
    die("Query Failure: " . $query);
}

如上所述,上面的代码90%的时间都有效,但在某些情况下(我相信是由名称中的特殊字符引起的)它会失败。

以下是一些失败的案例:

INSERT INTO `que` (`name`, `ip`, `steamid`, `serverip`) VALUES ('Shrimp%20ᴳᵀ%20ƒ„%20s%20%20t', '****', 'STEAM_1:0:16045698', '178.32.48.195:27015')
INSERT INTO `que` (`name`, `ip`, `steamid`, `serverip`) VALUES ('★★%20—%20noichia%20—%20…★', '****', 'STEAM_1:0:103227484', '178.32.48.195:27015')
INSERT INTO `que` (`name`, `ip`, `steamid`, `serverip`) VALUES ('•%20rie%20Low%20¼rke%20¢%20Ù„', '*****', 'STEAM_1:1:60346821', '178.32.48.195:27015')

所有的帖子输入都用以下内容进行了净化(并不是说有人无论如何都可以发布糟糕的东西,因为只有我的服务器才能发布):

$mysql->real_escape_string

我做错什么了吗?

非常感谢您的帮助!

编辑:在我使用以下方法将请求发送到PHP之前,我还对URL进行了编码:

stock void URLEncode(char[] str, int len)
{
char[] str2 = new char[len * 3 + 1];
Format(str2, len * 3 + 1, "%s", str);
char ReplaceThis[20][] =  { "%", " ", "!", "*", "'", "(", ")", ";", ":", "@", "&", "=", "+", "$", ",", "/", "?", "#", "[", "]" };
char ReplaceWith[20][] =  { "%25", "%20", "%21", "%2A", "%27", "%28", "%29", "%3B", "%3A", "%40", "%26", "%3D", "%2B", "%24", "%2C", "%2F", "%3F", "%23", "%5B", "%5D" };
for (int x = 0; x < 20; x++) {
    ReplaceString(str2, len, ReplaceThis[x], ReplaceWith[x]);
}
if (strlen(str2) > len * 3) {
    LogError("statistics encode url exceeded length (%d): %s", len * 3, str2);
}
Format(str, len, "%s", str2);
if (strlen(str) > len - 1) {
    LogError("statistics encode url exceeded length (%d): %s", len, str);
}
}

正如其他人在评论中指出的那样,如果使用准备好的语句,这会容易得多。如果您需要在每个视图中插入多个记录,那么速度也会更快。

以下是如何更改代码。

$mysql = new mysqli("***", "****", "****", "****");
mysqli_set_charset($mysql,"utf8mb4");
if (isset($_POST["name"])) {
    $query = $mysql->prepare("INSERT INTO `que` (`name`, `ip`, `steamid`, `serverip`) VALUES (?, ?, ?, ?)")
    $query->bind_param("ssss", $name, $clientip, $steamid, $serverip.":".$serverport);
    if($query->execute()) {
        print 'ok';
    }
} else {
   print 'Sorry required data not found';
}

同样值得一提的是,您不需要显式关闭连接。