参数化SQL查询,优化用户注册PHP代码

slnd54

在这里对 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: ../");
      }
    }       
?>

是的,这目前正在运行;但我相信我可以打破它。欢迎任何和所有建议。

通常,代码会检查用户是否存在。如果没有,它会将它们添加到用户数据库中,然后创建一个随机位置供它们居住。

KIKO软件

几点指点:

职能

您已将所有内容置于 PHP 的全局范围内。对于小型应用程序,这是可以容忍的,但很快就会失控。会发生难以追踪的奇怪错误,因为您失去了对变量的控制。您意识到此问题的一个迹象是变量的编号:$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-injection问题做点什么,现在你只需要在一个地方而不是多处处理这个问题。

班级

说到结构,为什么不用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

但还有许多其他来源。这是一个非常常见的错误。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章