这里是PHP的新手,我一直在研究如何对我的SQL连接使用参数化查询。但是,我所看到的一切都让我认为每次都需要更改相同的值才能使用参数化查询。有没有办法使用参数化查询来缩小我目前正在对查询进行的操作?我对这些东西的理解是错误的吗?
我可能是PHP新手,但总的来说,我知道的足够多了,我知道这段代码很烂。我不喜欢有多个select *查询,然后通过关联引用我需要的字段。但是我也有问题不是这样做的。有没有人能看一眼这个,然后把我推向正确的方向?我已经准备好被称为哑巴了,所以带上它吧。:)谢谢。
<?php
session_start();
// initializing variables
$username = "";
$email = "";
$errors = array();
// connect to the database
$db = mysqli_connect('db_server', 'db_user', 'db_pw', 'db_name');
// REGISTER USER
if (isset($_POST['register-submit'])) {
// receive all input values from the form
$username = mysqli_real_escape_string($db, $_POST['reg_username']);
$email = mysqli_real_escape_string($db, $_POST['reg_email']);
$password_1 = mysqli_real_escape_string($db, $_POST['reg_password_1']);
$password_2 = mysqli_real_escape_string($db, $_POST['reg_password_2']);
$actcode = mysqli_real_escape_string($db, $_POST['reg_actcode']);
// form validation: ensure that the form is correctly filled ...
// by adding (array_push()) corresponding error unto $errors array
if (empty($username)) { array_push($errors, "Username is required"); }
if (empty($email)) { array_push($errors, "Email is required"); }
if (empty($password_1)) { array_push($errors, "Password is required"); }
if ($password_1 != $password_2) { array_push($errors, "The two passwords do not match"); }
if ($actcode != "tobecaps") { array_push($errors, "Wrong activation code"); }
// first check the database to make sure
// a user does not already exist with the same username and/or email
$user_check_query = "SELECT * FROM `users` WHERE user_name='$username' OR user_email='$email' LIMIT 1";
$result = mysqli_query($db, $user_check_query);
$user = mysqli_fetch_assoc($result);
if ($user) { // if user exists
if ($user['user_name'] === $username) {
array_push($errors, "Username already exists");
}
if ($user['user_email'] === $email) {
array_push($errors, "email already exists");
}
}
// Finally, register user if there are no errors in the form
if (count($errors) == 0) {
$password = md5($password_1);//encrypt the password before saving in the database
$query1 = "INSERT INTO `users` (user_name, user_email, user_password, user_register_time) VALUES('$username', '$email', '$password', 'time()')";
mysqli_query($db, $query1);
$query2 = "SELECT * FROM `users` WHERE user_name='$username' LIMIT 1";
$result2 = mysqli_query($db, $query2);
$new_user = mysqli_fetch_assoc($result2);
$user_id = $new_user['user_id'];
$planet_found = false;
while (!$planet_found) {
$galaxy = mt_rand(1, 1);
$system = mt_rand(1, 15);
$planet = mt_rand(1, 15);
$query3 = "SELECT * FROM `planets` WHERE planet_galaxy='$galaxy' AND planet_system='$system' AND planet_planet='$planet' LIMIT 1";
$result3 = mysqli_query($db, $query3);
$planet_result = mysqli_fetch_assoc($result3);
if (!$planet_result) {
$planet_found = true;
}
}
$query4 = "INSERT INTO `planets` (planet_user_id, planet_galaxy, planet_system, planet_planet) VALUES('$user_id', '$galaxy', '$system', '$planet')";
$result4 = mysqli_query($db, $query4);
$query5 = "SELECT * FROM `planets` WHERE planet_user_id='$user_id' LIMIT 1";
$result5 = mysqli_query($db, $query5);
$planets_info = mysqli_fetch_assoc($result5);
$planets_id = $planets_info['planet_id'];
$query6 = "UPDATE `users` SET user_home_planet_id='$planets_id', user_galaxy='$galaxy', user_system='$system', user_planet='$planet' WHERE user_id='$user_id'";
$result6 = mysqli_query($db, $query6);
//update tables with new ids here
$_SESSION['username'] = $username;
$_SESSION['success'] = "You are now logged in";
header("Location: ../");
} else {
header("Location: ../");
}
}
?>
是的,这是目前正在工作;但我相信我可以打破它。欢迎提出任何建议。
通常,代码会检查用户是否存在。如果没有,它会将它们添加到用户数据库中,然后为它们创建一个随机位置。
发布于 2018-07-05 07:00:00
几点建议:
函数
您已经将所有内容都放在了PHP的全局作用域中。对于小型应用程序,这是可以容忍的,但很快就会失去控制。奇怪的bug将会发生,很难追踪,因为你失去了对变量的控制。注意到这个问题的一个标志是变量的编号:$result1
、$result2
、$result3
等。最好在函数的范围内执行每个查询,只有在需要时才返回结果。
不要重复自己(DRY原则)
你的代码中有很多重复的地方。通过在函数中收集非常相似的代码,您可以使您的代码更具可读性,获得函数的好处,并使更改更容易。例如:将此模式重复几次:
$query = "SELECT * FROM `table` WHERE column = value LIMIT 1";
$result = mysqli_query($db,$query);
$data = mysqli_fetch_assoc($result);
您可以将其放入一个函数中:
function retrieveDataRow($db,$table,$column,$value)
{
$query = "SELECT * FROM `$table` WHERE `$column` = $value LIMIT 1";
$result = mysqli_query($db,$query);
return mysqli_fetch_assoc($result);
}
这只是一个简单的例子,请仔细阅读sql-injection
段落。我的观点是,您可以编写此函数一次,然后多次使用它的功能。另外,假设您想要处理sql注入问题,现在您只需在一个地方而不是多个地方处理此问题。
类
说到结构,为什么不使用mysqli的面向对象接口,而不是过程接口呢?我不相信这是一个有意识的选择。在使用PHP时,您会发现几乎所有内容都是使用类编写的,因此也使用mysqli的面向对象接口似乎是合乎逻辑的。最终,这是你的选择,但你必须考虑这一点。请参见:
http://php.net/manual/en/mysqli.quickstart.dual-interface.php
错误检查
如果一切顺利,您的代码将执行得很好,但是如果出现问题,您的代码将如何处理?在我看来,不是很好。您不会检查查询执行的结果。例如:mysqli_query()
将在失败时返回FALSE
,而不是关联数据数组。至少检查一下:
$result = mysqli_query($db,$query);
if ($result !== FALSE) {
.... your code ....
} else error('Query error: '.mysqli_error($db));
sql注入
您可以直接在查询字符串中插入变量。不能称之为‘参数化查询’,已经有相关的书籍,但是mysqli基本上是通过绑定参数来防止sql注入的,请看:
https://websitebeaver.com/prepared-statements-in-php-mysqli-to-prevent-sql-injection
但还有许多其他来源。这是一个很常见的错误。
https://stackoverflow.com/questions/51181299
复制相似问题