Setup
We will be using PHP and MySQL to develop and set up this system.
Creating The Database
The following instructions will be shown with the phpMyAdmin client.
We are going to name our database "acc_tutorial", however you can name it anything.
Next, you need to create a table. We will name our table "accounts".
Next, we need to setup the table. Ensure you check A_I for id
. This stands for "auto incrementing", a value that will go up per entry. This will be our primary key also (which phpMyAdmin handles for us upon ticking this option). A primary key is a value that is unique per entry.
Now, I could have just given you the SQL to do this all automatically, however I believe it is better for you to learn. Click "save" and let's move on.
Configuration
Next, we need to setup the connection to MySQL. In this tutorial we will be using MySQLi, which should be included with your version of PHP.
The below code is our config file. Create a folder in the root of your project called includes
. Inside of this, create a file called config.php
. Edit this file and place the following code.
<?php
define('DB_SERVER', 'localhost'); // usually localhost, but if you use a remote database change this to what they give you
define('DB_USERNAME', 'root'); // your mysql username
define('DB_PASSWORD', ''); // your mysql password
define('DB_NAME', 'acc_tutorial'); // your database name from earlier
$conn = new mysqli(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
if ($conn->connect_error) {
// Do whatever you want if the connection fails. This error will more than likely be printed to your error log file on disk.
}
?>
This file will be "included" in every page, allowing each page to interact with MySQL without you having to paste the same code. This mechanic can also be used in a similar way to achieve a navbar, header, etc that changes across the entire website when you change one file.
Register
Next, we will be making the register page. Leave the includes
folder, back to your root. Create a file called register.php
. Edit this file and place the following content.
<?php
require_once('includes/config.php'); // this will allow us to access code from within this file, without it affecting the flow of our current code
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// get the details from the post form
// we use mysqli_real_escape_string because we do not want the user to exploit our database using SQL injection
$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = $_POST['password']; // this will be hashed later, so we do not have to real escape this
$confirm_password = $_POST['confirm_password'];
// run some checks to see if they can register
if(empty($username)) {
$error = "Username must not be empty.";
}
else if (empty($password)) {
$error = "Password must not be empty.";
}
else if($password != $confirm_password) {
$error = "Passwords do not match.";
}
else if(!ctype_alnum($username)) {
$error = "Username must be from a-zA-Z0-9 only."; // Change this message however you like.
}
// username is fine to be used
else {
$sql = "SELECT * FROM `accounts` WHERE `username` = '$username'";
$result = $conn->query($sql);
$rowcount = $result->num_rows;
// if this username is taken
if($rowcount > 0) {
$error = "Username has been taken already.";
}
// the user can register!
else {
// now let's set up their new account!
$password_hashed = password_hash($password, PASSWORD_DEFAULT); // change this method of hashing if you want, just ensure it is hashed for user privacy
if($conn->query("INSERT INTO `accounts` (`id`, `username`, `password`, `created_at`) VALUES (NULL, '$username', '$password_hashed', NOW());")) {
// registered! redirect to login
header('location: login.php');
exit();
}
else {
// hopefully nobody sees this
$error = "Failed to register. Please contact us ASAP.";
}
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Account Tutorial</title>
</head>
<body>
<?php if(!empty($error)) { ?>
<b><?=htmlspecialchars($error);?></b>
<?php } ?>
<form action="register.php" method="post">
<label>Username: </label>
<input type="text" name="username"><br>
<label>Password: </label>
<input type="password" name="password"><br>
<label>Confirm Password: </label>
<input type="password" name="confirm_password"><br>
<button type="submit">Register</button>
</form>
</body>
</html>
Feel free to style this however you want. The main thing is you have to keep the name param per input.
Login
Next, we will set up the portal for the user to login to their account. Create a file called login.php
next to the register.php
file. Edit the file and place the following content.
<?php
require_once('includes/config.php'); // this will allow us to access code from within this file, without it affecting the flow of our current code
// start a session
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// get the details from the post form
// we use mysqli_real_escape_string because we do not want the user to exploit our database using mysql injection
$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = $_POST['password']; // this will be hashed later, so we do not have to real escape this
// run some checks to see if they can login
if(empty($username)) {
$error = "Username must not be empty.";
}
else if (empty($password)) {
$error = "Password must not be empty.";
}
else if(!ctype_alnum($username)) {
$error = "Username must be from a-zA-Z0-9 only."; // Change this message however you like.
}
// username is fine to be used
else {
$sql = "SELECT * FROM `accounts` WHERE `username` = '$username'";
$result = $conn->query($sql);
$rowcount = $result->num_rows;
// if this username is taken
if($rowcount <= 0) {
$error = "Account does not exist, or incorrect password."; // do not allow them to bruteforce usernames
}
// the user can login!
else {
// fetch the info of the account that was found
$row = $result->fetch_assoc();
if(!password_verify($password, $row['password'])) {
$error = "Account does not exist, or incorrect password."; // do not allow them to bruteforce usernames
}
else {
// success! let's log them in.
$_SESSION['logged_in'] = true;
$_SESSION['id'] = $row['id'];
$_SESSION['username'] = $row['username']; // take the username from the DB
// redirect to index.php
header('location: index.php');
exit();
}
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Account Tutorial</title>
</head>
<body>
<?php if(!empty($error)) { ?>
<b><?=htmlspecialchars($error);?></b>
<?php } ?>
<form action="login.php" method="post">
<label>Username: </label>
<input type="text" name="username"><br>
<label>Password: </label>
<input type="password" name="password"><br>
<button type="submit">Login</button>
</form>
</body>
</html>
Home Page
Here is where we only want people with accounts to access. Make a new file called index.php
in the same directory as login.php
and register.php
. Edit the file and place the following content.
<?php
session_start();
// redirect if user is not logged in.
if(!$_SESSION['logged_in']) {
header('location: login.php');
exit();
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Account Tutorial</title>
</head>
<body>
<p>Welcome, <b><?=$_SESSION['username'];?></b>!</p>
</body>
</html>
Again, feel free to style however you want etc.
Conclusion
This should give you a grasp on how PHP and MySQL work, and how HTML can be used to interact with PHP. The concept is easy to grasp, just keep trying if you haven't already figured it out.