PHP New User Creation I'm learning more about PHP, so I've decided to create a simple login/create account system. Entering information for creating a new account sends the data to my localhost machine, using MySQLi and the web server MySQL. I'm looking for feedback about security, efficiency, and overall code. I would like to kick old habits to the curb before it's too late. Any and all help is appreciated and considered. Thank you in advance!

create.html

&lt;!DOCTYPE html&gt;
&lt;html lang="en-US"&gt;
    &lt;head&gt;
        &lt;meta charset="UTF-8"&gt;
        &lt;title&gt;create.html&lt;/title&gt;
        &lt;script src="script.js"&gt;&lt;/script&gt;
        &lt;link rel="stylesheet" type="text/css" href="style.css"&gt;
    &lt;/head&gt;
    &lt;body bgcolor="pink"&gt;
        &lt;center&gt;
            &lt;form action="create.php" method="post"&gt;
                &lt;label&gt;Username&lt;/label&gt;
                &lt;input type="text" name="username"&gt;&lt;br&gt;
                &lt;label&gt;Password&lt;/label&gt;
                &lt;input type="password" name="password"&gt;&lt;br&gt;
                &lt;label&gt;Re-enter Password&lt;/label&gt;
                &lt;input type="password" name="confirm_password"&gt;&lt;br&gt;
                &lt;button type="submit"&gt;Create Account&lt;/button&gt;
            &lt;/form&gt;
        &lt;/center&gt;
    &lt;/body&gt;
&lt;/html&gt;


create.php

&lt;!DOCTYPE html&gt;
&lt;html lang="en-US"&gt;
    &lt;head&gt;
        &lt;meta charset="UTF-8"&gt;
        &lt;title&gt;create.php&lt;/title&gt;
    &lt;/head&gt;
    &lt;body bgcolor="pink"&gt;
        &lt;?php

            $servername = "localhost";
            $username = "XXXXXXXXXX"; // Not shown
            $password = "XXXXXXXXXX"; // Not shown
            $dbname = "Database";

            //Create connection
            $mysqli = new mysqli($servername, $username, $password, $dbname);

            //Test connection
            if ($mysqli-&gt;connect_error) {
                die("Connection failed: " . $mysqli-&gt;connect_error);
            }

            $new_user_usr = filter_input(INPUT_POST, 'username');
            $new_user_pwd = filter_input(INPUT_POST, 'password');
            $new_user_pwd_conf = filter_input(INPUT_POST, 'confirm_password');

            $sql = "SELECT usr, pwd FROM Users";
            $result = $mysqli-&gt;query($sql);

            if($result-&gt;num_rows &gt; 0) {

                /* If passwords don't match */
                if($new_user_pwd !== $new_user_pwd_conf) {
                    die("Passwords don't match");
                }

                /* If password isn't between bounds */
                if(strlen($new_user_pwd) &lt;= 7 || strlen($new_user_pwd) &gt;= 13) {
                    die("Password not long enough! Must be at least 8 characters long, but not greater than 12 characters");
                }

                /* If username is the same as password*/
                if($new_user_usr === $new_user_pwd) {
                    die("Username cannot equal password!");
                }

                while($row = $result-&gt;fetch_assoc()) {
                    if($row['usr'] === $new_user_usr) {
                        die("Username already taken");
                    }
                }

                $add = "INSERT INTO Users (usr, pwd) VALUES ('$new_user_usr', '$new_user_pwd')";

                echo $mysqli-&gt;query($add) ? "user created successfully" : "Error: " . $add . "&lt;br&gt;" . $mysqli-&gt;error;

            }

        ?&gt;
    &lt;/body&gt;
&lt;/html&gt;
I would like to kick old habits to the curb 


That's a very good intention. Especially given that the present code, sadly, is rather a display of such old habits. 

In order to improve, consider learning the following essentials:


PDO prepared statements (be advised that PDO is superior to mysqli for learners). Basically all your queries involving variables must be run not via query() but via prepare()/execute(), with all variables in the query substituted with placeholders.
Password hashing is essential. Just follow the simple example and store in the database not the original password but the result of password_hash() function's call.


there is no reason to limit the maximum password length. Let a user have the password as big as they wish.

the proper error reporting. first of all, always configure PHP to report errors by itself. And then never write a single line of code that intentionally outputs the error message. It's your server's configuration should be responsible for the errors' output.
Use a better code structure. Consider having both the HTML form and the handler sharing the same address, making the file with the form not called directly but included by the PHP file on demand. It will let you to utilize the POST/Redirect/Get pattern. Among other things it will let you to show errors nicely instead of bluntly aborting the script execution to show one. Collect all errors in the array and then run your query only if it is empty. Show the form back along the errors and the entered data otherwise. 


the code used for the database connection is better to be stored in a separate file and then just included into every script that will need it.

avoid the code that does nothing useful. For example, running a select query to get all users from the database in order to create a user just makes no sense. You can ditch both the query and the condition that follows.


Taking all the above into consideration your code could be rewritten like this

db.php:

$host = '127.0.0.1';
$db   = 'Database';
$user = 'XXX';
$pass = 'XXX';
$charset = 'utf8mb4';

$options = [
    PDO::ATTR_ERRMODE            =&gt; PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   =&gt; false,
];
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
try {
     $pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
     throw new \PDOException($e-&gt;getMessage(), (int)$e-&gt;getCode());
}


create_user.php

$errors = [];
if ($_POST)
{
    require 'db.php';

    $username = filter_input(INPUT_POST, 'username');
    $password = filter_input(INPUT_POST, 'password');
    $pwd_confirm = filter_input(INPUT_POST, 'confirm_password');

    if ($password !== $pwd_confirm) {
        $errors[] = "Passwords don't match";
    }
    if (strlen($password) &lt; 8) {
        $errors[] = "Password not long enough! Must be at least 8 characters long";
    }
    if ($username === $password) {
        $errors[] = "Username cannot equal password!";
    }

    $stmt = $pdo-&gt;query("SELECT 1 FROM Users WHERE usr = ?");
    $stmt-&gt;execute([$username]);
    $user_found = $stmt-&gt;fetchColumn();
    if ($user_found) {
        $errors[] = "Username already taken";
    }
    if (!$errors)
    {
        $hashed_password = password_hash($password, PASSWORD_DEFAULT);
        $stmt = $pdo-&gt;prepare("INSERT INTO Users (usr, pwd) VALUES (?, ?)");
        $stmt-&gt;execute([$username, $hashed_password]);
        header("Location: ."); // consider redirecting to the user profile
        exit;
    }
} else {
    $username = "";
}

include 'form.php';


form.php

&lt;!DOCTYPE html&gt;
&lt;html lang="en-US"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;create.html&lt;/title&gt;
    &lt;script src="script.js"&gt;&lt;/script&gt;
    &lt;link rel="stylesheet" type="text/css" href="style.css"&gt;
&lt;/head&gt;
&lt;body bgcolor="pink"&gt;
&lt;center&gt;
    &lt;?php foreach ($errors as $error): ?&gt;
        &lt;p&gt;&lt;?= $error ?&gt;&lt;/p&gt;
    &lt;?php endforeach ?&gt;
    &lt;form method="post"&gt;
        &lt;label&gt;Username&lt;/label&gt;
        &lt;input type="text" name="username" value="&lt;?= htmlspecialchars($username) ?&gt;"&gt;&lt;br&gt;
        &lt;label&gt;Password&lt;/label&gt;
        &lt;input type="password" name="password"&gt;&lt;br&gt;
        &lt;label&gt;Re-enter Password&lt;/label&gt;
        &lt;input type="password" name="confirm_password"&gt;&lt;br&gt;
        &lt;button type="submit"&gt;Create Account&lt;/button&gt;
    &lt;/form&gt;
&lt;/center&gt;
&lt;/body&gt;
&lt;/html&gt;