I’m setting up a registration/login in system for my online trivia game and have come up with a dynamic way to check for username duplicates in a MySQL Database Table in real time.
First the Vanilla-JS script:
'use strict';
const d = document;
const sendUrl = 'checkName.php'; // Name of php file:
const unavailable = d.querySelector('.unavailable');
var username = d.querySelector('#username');
var checkUsername = {};
/* Success function utilizing FETCH */
const checkUISuccess = function (status) {
/*
* Make <span> HTML tag visible to highlight message
* in red.
*/
if (status) {
unavailable.style.display = "inline-block";
} else {
unavailable.style.display = "none";
}
};
/* If Database Table fails to update data in mysql table */
const checkUIError = function (error) {
console.log("Database Table did not load", error);
};
/*
* Grab the status if there is an error.
*/
const handleSaveErrors = function (response) {
if (!response.ok) {
throw (response.status + ' : ' + response.statusText);
}
return response.json();
};
/*
* Fetch ($.get in jQuery) that basic is a simplified newer Ajax
* protocol (function?).
*/
const checkRequest = (sendUrl, succeed, fail) => {
fetch(sendUrl, {
method: 'POST', // or 'PUT'
body: JSON.stringify(checkUsername)
})
.then((response) => handleSaveErrors(response))
.then((data) => succeed(data))
.catch((error) => fail(error));
};
/*
* Grab the keystrokes
*/
const checkForDuplicate = (e) => {
e.preventDefault();
checkUsername.username = username.value; // Put the keystrokes in object var:
/*
* Call the checkRequest Function using sendUrl variable as the name
* of the php file that will be used to check against the database table.
*/
checkRequest(sendUrl, checkUISuccess, checkUIError);
};
/*
* Add an Event Listener to check for username already in
* database table. When the person types every keyup stroke
* is checked against the database table.
*/
username.addEventListener('keyup', checkForDuplicate, false);
The HTML
<form class="registerForm" action="" method="post" autocomplete="on">
<h1><?php echo (isset($message)) ? $message : 'Register'; ?></h1>
<p><?php echo (isset($errPassword)) ? $errPassword : "Please fill in this form to create an account."; ?></p>
<hr>
<label for="username"><b>Username <span class="unavailable"> - Not Available, please choose a different one.</span></b></label>
<input id="username" type="text" placeholder="<?php echo (isset($statusUsername) && $statusUsername) ? "Username is not available, please re-enter!" : "Enter Username"; ?>" name="data[username]" value="" autofocus required>
<label for="email"><b>Email</b></label>
<input type="text" placeholder="Enter Email" name="data[email]" value="<?php echo (isset($data['email'])) ? $data['email'] : null; ?>" required>
<label for="psw"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="data[password]" required>
<label for="psw-repeat"><b>Repeat Password</b></label>
<input type="password" placeholder="Repeat Password" name="data[repeatPassword]" required>
<hr>
<p>By creating an account you agree to our <a href="#">Terms & Privacy</a>.</p>
<input type="submit" name="submit" value="enter" class="registerbtn">
<div class="signin">
<p>Already have an account? <a href="index.php">Sign in</a>.</p>
</div>
</form>
the checkName.php
<?php
require_once 'assets/config/config.php';
require_once "vendor/autoload.php";
require_once 'loginFunctions.php';
use Library\Users;
use Library\Database as DB;
$db = DB::getInstance();
$pdo = $db->getConnection();
/*
* The below must be used in order for the json to be decoded properly.
*/
$data = json_decode(file_get_contents('php://input'), true);
/*
* Check to see if username already exists
* in the MySQL Database Table (members).
*/
function duplicateUsername($username, $pdo) {
$query = "SELECT 1 FROM members WHERE username = :username";
$stmt = $pdo->prepare($query);
$stmt->bindParam(':username', $username);
$stmt->execute();
$row = $stmt->fetch();
if ($row) {
return true; // userName is in database table
} else {
return false; // Username isn't in database table
}
}
$username = trim($data['username']);
$status = duplicateUsername($username, $pdo);
output($status);
/*
* After encoding data to JSON send back to javascript using
* these functions.
*/
function errorOutput($output, $code = 500) {
http_response_code($code);
echo json_encode($output);
}
function output($output) {
http_response_code(200);
echo json_encode($output);
}
and a little bit of the CSS
.unavailable { display: none; color: #cf0004; font-style: italic; }
.registerForm {
display: block;
width: 100%;
max-width: 600px;
height: auto;
background-color: #fff;
padding: 16px;
margin: 20px auto;
/* Full-width input fields */
input[type=text], input[type=password] {
width: 100%;
padding: 15px;
margin: 5px 0 22px 0;
display: inline-block;
border: none;
background: #f1f1f1;
}
input[type=text]:focus, input[type=password]:focus {
background-color: #ddd;
outline: none;
}
/* Overwrite default styles of hr */
hr {
border: 1px solid #f1f1f1;
margin-bottom: 25px;
}
/* Set a style for the submit/register button */
.registerbtn {
background-color: #4CAF50;
color: white;
padding: 16px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
text-transform: capitalize;
font-size: 1.2em;
width: 100%;
opacity: 0.9;
&:hover {
opacity:1;
}
}
Sorry, it’s written in Sass, but I think it would be easy to decipher. I hope this will give someone help in doing something like this and/or how to use Fetch. Just a note Fetch is supported by all browsers though it’s mostly older browsers. Though if you are concerned about that you can probably find a polyfill for the script, but as for me I don’t worry about that too much.

I was just using old code and failed to realize that the I had the try-catch block as I was just busy trying to get the json portion working. I don’t like typing and this is something that I’m bad at not checking the old code. I’m going take out that out. Nice catch, I basically have stop using try-catch blocks as I’m a small operation and that just slipped through the cracks. I’m going to do the unique index on the server side and get rid of duplication function for that side of validation. Though I think I’m going to do that for the email address as I was just using duplicate more for gameplay than security. While I still like people to have a unique username, it wouldn’t hurt if there was a duplicate username. It will just look a little funny on the high scores listing. I still have to implement a few things on both the server side and the client side when it comes to validation.