I need to generate unique username automatically, do you think these two functions can work?
function km_create_random_username($db_user_conn){
//set the random id length
$km_random_username_length = 6;
//generate a random id encrypt it and store it in $rnd_id
$km_random_username = uniqid(rand(),1);
//to remove any slashes that might have come
$km_random_username = strip_tags(stripslashes($km_random_username));
//Removing any . or / and reversing the string
$km_random_username = str_replace(".","",$km_random_username);
$km_random_username = strrev(str_replace("/","",$km_random_username));
//finally I take the first 6 characters from the $km_rnd_id
$km_random_username = substr($km_random_username,0,$km_random_username_length);
if(!km_check_random_username($db_user_conn, $km_random_username)){
return $km_random_username;
}
}
function km_check_random_username($db_user_conn, $km_random_username) {
$query = "SELECT km_user_username FROM km_users WHERE km_user_username=?";
$stmt = mysqli_prepare($db_user_conn, $query);
mysqli_stmt_bind_param($stmt, 's', $km_random_username);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
$rows = mysqli_stmt_num_rows($stmt);
mysqli_stmt_fetch($stmt);
if($rows > 0) {
km_create_random_username($db_user_conn);
}else{
return false;
}
}
Iām trying to decide whether youāre just going to get into a never-ending spiral. Your create function calls your check function, which, if it finds the name already exists, calls the create function. I think Iād prefer to have the create function just loop around creating, then checking, and have the check function only check. The check function would return a Boolean, and the create function would keep running until it is sure the name is unique.
In your check routine, thereās no need to call fetch, is there? All you care about is whether you found zero or one entry for that username.
Hi @SamA74 thanks for your answer, so if the table username is unique and I put the insert query into a try/catch block then when an exception is created I need to call the function km_create_random_username again in the catch block and try with another insert which I suppose I need to put again in the catch block is it correct?
repeat to create and insert a new user name until no exception is thrown. I would say the user name creation could be simplified, just have a look at this functions examples:
Hi @droopsnoot thanks for your help. The function make_new_username() does generate the username and checks if it is already in the database then if it is in the database return true other wise false? Is it correct? Do I still need to use unique index for the table username? Thanks for your patience
do {
$name = km_create_random_username()
} while ( ! km_insert_username($name) )
If km_insert_username executes a database query āINSERT INTO table(ānameā) VALUES(?)ā (and then feeds it the $name parameter), and the table has a UNIQUE condition on ānameā, then the query should return either a success (an object of some form), or FALSE.
If it returns false, then ! FALSE = TRUE. And the loop will continue (because the while condition was true, so it starts over). If it returns something other than false (which is when it actually inserts a row), then ! (something) is FALSE, and the loop terminates.
This of course assumes you donāt set your database connection to throw an exception on error; otherwise you have to try-catch it:
do {
try {
$name = km_create_random_username()
km_insert_username($name)
break;
} catch {
}
} while ( true )
same theory, but this time instead of returning āfalseā, the query will throw an exception, which pushes code execution into the catch block. The catch block does nothing, you hit the while, and go back to the top because true is always true. Once you DONāT get an exception (because it succeeded in inserting a row), the code will continue to the ābreakā,which terminates the loop.
To look at it from a completely different perspective:
What IS your database table layout? Why wouldnāt you make username a unique (or even Primary Key) of that table?
If the table layout suggests/requires you to put that unique condition in place, as droop and others have said, use what is available to you; the database can in one query do both the check and insert-if-allowed, rather than having to make two queries.
Itās going to be difficult to test as a full function without subverting the code (thus defeating the purpose of the test) or filling your database with a lot of test data.
You can test individual parts of the code simply enough by mocking the results of the parts you arent testing at any given time. This is called Mocking.
You can test the whole function if youāre willing to flood your table with test data (obviously, donāt do this in production environment!). I would add a $tries counter to 0, and then inside your catch block, set to increment said counter; loop the function to try and create several thousand usernames, and see if any of the results have a counter value greater than 0ā¦