我做了这个脚本,这给我带来了很多麻烦。我不太擅长MySQL,也许我正在尝试做一些对我的SQL知识来说太高级的事情,但我真的真的真的很想让这个工作。
我的php脚本是:<?PHP
$getusername=$_GET['user'];
$getpassword=$_GET['pass'];
$getworldname=$_GET['worldname'];
$getblock=$_GET['block'];
$getpos=$_GET['pos'];
$user_name = "asdasdasd";
$password = "asdasd";
$database = "asdasd";
$server = "localhost";
$db_handle = mysql_connect($server, $user_name, $password);
$db_found = mysql_select_db($database, $db_handle);
$SQL="SELECT * FROM accounts WHERE username='$getusername' and password='$getpassword'";
$result=mysql_query($SQL);
$count=mysql_num_rows($result);
if($count==1){
$blockstring=$getpos.'/'.$getblock.'|';
$SQL="SELECT LOCATE('$getpos', blocks) FROM worlds WHERE name='$getworldname'";
$result=mysql_query($SQL);
$count=mysql_num_rows($result);
echo $count;
//if there's already that block
if ($result!=0){
$posUnknown='|'.$getpos.'/';
$posKnown='|'.$getpos.'/'.$getblock;
$SQL="UPDATE worlds SET blocks=replace(blocks,concat('$posUnknown',substring_index(substring_index(blocks, '$posUnknown', 2), '|', 1),'|'),'$posKnown') WHERE name='$getworldname'";
$result=mysql_query($SQL);
}else{
$SQL="UPDATE worlds SET blocks=CONCAT(blocks,'$blockstring') WHERE name='$getworldname'";
$result=mysql_query($SQL);
}
print 'OK';
}else{
print 'NO';
}
?>
我确信我犯了一些错误,也是大的查询,但遗憾的是我不能弄清楚我做错了什么。
块内容的一个例子可以是:
x10y20z30/0 | x999y1231z30/1 | x3330y4444z0/99999 |等
这个脚本做的,我想让它做的是:
- 检查用户名和密码,幸运的是,这是有效的,
- 检查给定的块是否已经存在于"blocks"中
- 如果存在,则替换
- 的值(/后面的值)已经存在的块与新的块,
- 如果它不存在,直接添加到"blocks"中。
但它不起作用,我知道为什么。我知道这是因为SQL,但我不知道如何使它工作。
您的代码的安全性有一些严重的问题,正如在注释中指出的那样。我已经做了我能做的,而没有真正改变你的代码的功能:
<?PHP
$getusername=$_GET['user'];
$getpassword=$_GET['pass'];
$getworldname=$_GET['worldname'];
$getblock=$_GET['block'];
$getpos=$_GET['pos'];
$user_name = "asdasdasd";
$password = "asdasd";
$database = "asdasd";
$server = "localhost";
你应该使用mysqli,而不是mysql:
$db = new mysqli($server, $user_name, $password, $database);
在real_escape_string:
查询中使用之前,所有输入都需要进行转义 $SQL="SELECT * FROM accounts WHERE username='" . $db->real_escape_string($getusername) . "' and password='" . $db->real_escape_string($getpassword) . "'";
$result=$db->query($SQL);
$count=$result->num_rows;
if($count==1) {
$blockstring=$getpos.'/'.$getblock.'|';
$SQL="SELECT LOCATE('" . $db->real_escape_string($getpos) . "', blocks) FROM worlds WHERE name='" . $db->real_escape_string($getworldname) . "'";
$result=$db->query($SQL);
$count=$result->num_rows;
echo $count;
//if there's already that block
if ($count!=0) {
$posUnknown='|'.$getpos.'/';
$posKnown='|'.$getpos.'/'.$getblock;
这可能是您遇到问题的地方,因为看起来您将所有这些信息存储在一行中:
$SQL="UPDATE worlds SET blocks=replace(blocks,concat('" . $db->real_escape_string($posUnknown) ."',substring_index(substring_index(blocks, '" . $db->real_escape_string($posUnknown). "', 2), '|', 1),'|'),'" . $db->real_escape_string($posKnown) . "') WHERE name='" . $db->real_escape_string($getworldname). "'";
$result=$db->query($SQL);
} else {
$SQL="UPDATE worlds SET blocks=CONCAT(blocks,'" . $db->real_escape_string($blockstring) ."') WHERE name='" . $db->real_escape_string($getworldname) . "'";
$result=$db->query($SQL);
}
print 'OK';
} else {
print 'NO';
}
?>
因为你所有的块信息都被塞在一个列中,你的数据库根本没有规范化,看起来像这样:
Worlds
name blocks
你的数据库应该更像这样构建:
Worlds
id | name
---------------
1 | demoworld
Blocks
id | WorldID | x | y | z | data
-----------------------------------------
1 | 1 | 10 | 20 | 30 | 0
2 | 1 | 999 | 1231 | 30 | 1
3 | 1 | 33330 | 4444 | 0 | 99999
您可以在查询数据时重新创建您提供的数据布局,当有人试图添加类似x20y30z40/12345的内容时,您可以解析它以获得x、y、z和数据部分。