I need to generate unique username automatically, I've created two functions, one to create a random username and the other one to check if the username is already stored in the database. 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;
}
}
To test that the code spots duplicates and then generates a new randon username do this.
Either empty the table km_user or record the last id value
Run the km_check_random_username() function twice manually passing the same username both time.
km_check_random_username($db_user_conn, 'ItsMee');
km_check_random_username($db_user_conn, 'ItsMee');
Check the table? Did it create the ItsMee username?
Did it create a random username after creating the ItsMe username? If it did, then it spotted the Dup and ran the regenerate phase
echo gen_random_username(10);
// generates jPMNfrQZil
function gen_random_username($db_user_conn, $length){
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$random_username = "";
for($i = 0; $i < $length; $i++){
$random_username .= $chars[rand(0,strlen($chars)-1)];
}
if(!km_check_random_username($db_user_conn, $random_username)){
return $random_username;
}
}
// I didn't check this function, but I modified it to use the above function
// gen_random_username($x, $length)...
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) {
gen_random_username($db_user_conn, 10);
}else{
return false;
}
Related
I have created the following function to fetch data from my database, but its capabilities are limited. Currently it can fetch one value at a time, which is fine for fetching the value of one column of one row, but as I progress with my work, I now want to be able to fetch multiple values in one call.
The Function:
function retrieve($value, $identifier = null) {
// Check if identifier is given
$identifier = (is_null($identifier)) ? "`ID` = '{$_SESSION["ID"]}'" : $identifier;
// Connect to the database
$connection = connect("limited");
// Pass query, get result and fetch value out of it
$query = "SELECT * FROM `users` WHERE $identifier";
$result = mysqli_query($connection, $query);
if (mysqli_num_rows($result) > 0) {
$data = mysqli_fetch_assoc($result);
return $data[$value];
}
mysqli_close($connection);
}
How I currently use it to fetch multiple values:
// Define variables
$x1 = retrieve("x1");
$x2 = retrieve("x2");
$x3 = retrieve("x3");
$x4 = retrieve("x4");
$x5 = retrieve("x5");
$x6 = retrieve("x6");
$x7 = retrieve("x7");
$x7 = retrieve("x8");
I have read other questions here on Stack Overflow, but none of them solves my problem as I use an optional parameter, which makes my life hard. For example, I thought of implementing the splat operator to allow unlimited parameters, but as I use the optional parameter $identifier, I can't make it into something like:
function retrieve($identifier = null, ...$value) {}
because it will use the first parameter as the identifier when I omit it.
I'm sure that regarding performance it would be better if I could fetch all the necessary values in one call of the function retrieve() instead of using it as shown above and that's why I would like to know:
How can I edit this function in order to fetch more values at once?
Calling it like so:
$x = retrieve($y);
$x1 = $y["x1"];
$x2 = $y["x2"];
...
EDIT:
Thanks to Manish Jesani for his help! I used his answer and modified to do exactly what I want. For anyone that may be interested in the future, here's the code:
function retrieve($value, $identifier = null) {
// Check if identifier is given
$values = array();
$identifier = (is_null($identifier)) ? "`ID` = '1'" : $identifier;
// Connect to the database
$connection = connect("limited");
// Pass query, get result and fetch value out of it
$query = "SELECT * FROM `users` WHERE $identifier";
$result = mysqli_query($connection, $query);
if (mysqli_num_rows($result) > 0) {
$data = mysqli_fetch_assoc($result);
if (is_array($value)) {
foreach($value as $_value) {
$values[$_value] = $data[$_value];
}
return $values;
}
else {
return $data[$value];
}
}
mysqli_close($connection);
}
You can call the function with as many parameters you want. Τo do this you have to use func_num_args() to get all of them, as shown below:
function retrieve() {
$args = func_num_args();
$query = "SELECT '".implode("','", func_get_args())."' FROM `users` WHERE $identifier";
$result = mysqli_query($connection, $query);
if (mysqli_num_rows($result) > 0) {
$data = mysqli_fetch_assoc($result);
return $data;
}
mysqli_close($connection);
}
You can call this function like this: $params = retrieve('x1','x2','x3').
Alternatively, you can retrieve them as variables list($x1, $x2, $x3) = retrieve('x1','x2','x3').
Please try this:
function retrieve($value, $identifier = null) {
// Check if identifier is given
$return = array();
$identifier = (is_null($identifier)) ? "`ID` = '{$_SESSION["ID"]}'" : $identifier;
// Connect to the database
$connection = connect("limited");
// Pass query, get result and fetch value out of it
$query = "SELECT * FROM `users` WHERE $identifier";
$result = mysqli_query($connection, $query);
if (mysqli_num_rows($result) > 0) {
$data = mysqli_fetch_assoc($result);
if(is_array($value))
{
foreach($value as $_value)
{
$return[$_value] = $data[$_value];
}
}
else
{
$return[$value] = $data[$value];
}
return $return;
}
mysqli_close($connection);
}
$x = retrieve(array("x1","x2","x3","x4","x5","x6"));
Can someone tell me if there's a better way doing this?
I am trying to generate a Serial number (function Taken from a Post on
this site )
Check in my database if this Serial exist, if it does,regenerate another
Insert Unique serial into Db
function GenerateSerial() {
$chars = array(0,1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
$sn = '';
$max = count($chars)-1;
for($i=0;$i<20;$i++){
$sn .= (!($i % 5) && $i ? '-' : '').$chars[rand(0, $max)];
}
return $sn;
}
// Generate SN
$serial = GenerateSerial() ;
// Check if it exists, then re-generate
function checkifSerialexist () {
$statement = $dbh->prepare("SELECT `id` FROM `table` WHERE `SN` = :existSN");
$statement->bindParam(':existSN', $serial, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
$result = $statement->fetchAll();
$serial_count = $statement->rowCount();
if ($serial_count > 0) {
$serial = GenerateSerial() ;
}
return $serial ;
}
//Now insert unique SN
$stmt = $dbh->prepare("INSERT INTO `table` (SN) VALUES (:sn)");
$stmt->bindParam(':sn', $serial, PDO::PARAM_STR);
ect....
You are not calling your checkifSerialexist() function nor are you sending the serial (and the database connection...) as a parameter.
It should be something like:
$serial = GenerateSerial() ;
while (checkifSerialexist($dbh, $serial))
{
$serial = GenerateSerial() ;
}
function checkifSerialexist ($dbh, $serial)
{
$statement = $dbh->prepare("SELECT `id` FROM `table` WHERE `SN` = :existSN");
$statement->bindParam(':existSN', $serial, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
$result = $statement->fetchAll();
return (count($result) > 0);
}
it's hard to say with the provided code, but my usual logic for unique generation is as follows:
$serial = genSerial();
while(!serialUnique($serial)) {
$serial = genSerial();
}
save($serial);
i always make my check functions (e.g. serialUnique) return a boolean.
It seems like your function that checks if the serial exists does not have the serial you generated earlier.
Depending on where your function is, it might not have access to the variable. Pass it as a parameter and return true or false from the checkIfSerialExists function.
function checkifSerialexist ($serial) {
$statement = $dbh->prepare("SELECT `id` FROM `table` WHERE `SN` = :existSN");
$statement->bindParam(':existSN', $serial, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
$result = $statement->fetchAll();
$serial_count = $statement->rowCount();
if ($serial_count > 0) {
return true;
} else {
return false;
}
}
Then from where you want to add it to the database, do something like
$serial = GenerateSerial() ;
if(checkifSerialexist($serial)) {
//Now insert unique SN
$stmt = $dbh->prepare("INSERT INTO `table` (SN) VALUES (:sn)");
$stmt->bindParam(':sn', $serial, PDO::PARAM_STR);
//ect....
}
echo implode('-', str_split(substr(strtoupper(md5(microtime().rand(1000, 9999))), 0, 20), 5));
this is just the simply way, you can apply more secure if you need, you can use sha1(), microtime() combined with anothers functions and unique user data, and check if serial generated exsists in your data base... litle bit more secure, like:
$user_mail = 'customer#domain.com';
function salt($leng = 22) {
return substr(sha1(mt_rand()), 0, $leng);
}
function serial(){
$hash = md5($user_mail . salt());
for ($i = 0; $i < 1000; $i++) {
$hash = md5($hash);
}
return implode('-', str_split(substr(strtoupper($hash), 0, 20), 5))
}
This exit: XXXX-XXXX-XXXX-XXXX serial pattern
I have the following code, sorry for the length but it saves explaining most of what i need...
the $result in the pages() function is not being returned. When I call for it all I get is undefined variable. Why?
What i need is to pass the $start and $display variables to the mysql query.
<?php
if(isset($_POST['get_records_submit'])) {
$pages; $start; $display; $result;
function pages($stmt) {
//set how many records per page
$display = 10;
//determine how many pages there are
if(isset($_GET['p']) && is_numeric($_GET['p'])) { //already determined
$pages = $_GET['p'];
}
else {
$records = mysqli_stmt_num_rows($stmt);
}
//calculate the number of pages
if($records > $display) { //if there are more records than will fit on one page
$pages = ceil($records/$display); //ceil() rounds up to the nearest integer
}
else { //records will fit on one page
$pages = 1;
}
//determine which row to start returning results from
if(isset($_GET['s']) && is_numeric($_GET['S'])) { //already determined
$start = $_GET['s'];
}
else {
$start = 0;
}
$result = array(0=>$display, 1=>$pages , 2=>$start);
return $result;
}
$searchby = $_POST['search_by'];
$searchfor = $_POST['search_for'];
$contact = 1;
$i = 0;
//set the initial query
$query = "SELECT client_id, title_desc, firstname, surname, house, street, town, city, county, postcode as count FROM address LEFT JOIN client USING (client_id) LEFT JOIN client_title USING (title_id) LEFT JOIN address_street USING (address_id) LEFT JOIN address_town USING (address_id) LEFT JOIN address_city USING (address_id) LEFT JOIN address_county USING (address_id) WHERE is_contact = ?";
//depending on search terms, amend the query
if($searchby == 'all') {
$query .= " ORDER BY surname ASC, firstname ASC";
$stmt = mysqli_prepare($dbc, $query);
mysqli_stmt_bind_param($stmt, 'i', $contact);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
pages($stmt);
var_dump ($result);
foreach ($result as $var) { echo $var.' ';}
mysqli_stmt_close($stmt);
$query .= " ORDER BY surname ASC, firstname ASC LIMIT ?, ?";
$stmt = mysqli_prepare($dbc, $query);
mysqli_stmt_bind_param($stmt, 'iii', $contact, $start, $display);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $client_id, $stitle, $sfname, $ssname, $shouse,$sstreet, $stown, $scity, $scounty, $spostcode);
if($searchfor != '') {
echo "<p>You searched under <span class=\"bold\">\"All\"</span>, therefore your search term <span class=\"bold\">\"$searchfor\"</span> has not been included.</p>";
}
}
}
In this line:
pages($stmt);
The function pages() returns the array, but this result is not being set to a variable. Try using:
$result = pages($stmt);
And then accessing the array via the variable $result.
That $result variable that you declared up top? The reason it's not being set is because the function pages() doesn't have access to it because it's not within the function's scope.
Edit
As Lyth pointed out, if you don't want the function to return anything, you can modify your function as follows:
function pages($stmt) {
global $result;
// ...
// The rest of your function
// ...
$result = array(0=>$display, 1=>$pages , 2=>$start);
// Remove the 'return $result' line
}
I do not know why you write $pages; $start; $display; $result;? If you want to get the value of array try to use this...
$result = array($display, $pages , $start);
return $result;
You can check the array with
print_r ($result);
Below is my code that i have written to create a random string. Works well. It also checks to make sure that the generated string doesn't already exist, and if it does, then it makes another one. HOWEVER i haven't yet worked out a way to make the code generated if one already exists be checked to see if that one exists. Would i be best doing an elseif statement?
PHP
<?PHP
require_once('dbConfig.php');
$randomstring = '';
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
for ($i = 0; $i < 12; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
//$generatedId = "SPI-E7HN2SBIIF5W";
$generatedId = 'SPI-'.$randomString;
//Prepare select query
$statement = $db->prepare("SELECT client_unique_id FROM clients WHERE client_unique_id = ? LIMIT 1");
//Determine variable and then bind that variable to a parameter for the select query ?
$id = $generatedId;
$statement->bind_param('s', $id);
//Execute and store result so that num_rows returns a value and not a 0
$statement->execute();
$statement->store_result();
//Bind result to a variable for easy management afterwards
$statement->bind_result($clientId);
// Generate a random ID for the user if the previously generated one already exists
if($statement->num_rows > 0){
$randomstring = '';
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
for ($i = 0; $i < 0; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
$generatedId = 'SPI-'.$randomString;
echo $generatedId;
} else {
// If there's no issue with what's been created, echo it out :)
echo $generatedId;
}
?>
Any help is appreciated :)
try this.
// initialize a variable to hold the last generated id,
$generatedId = '';
// and another to hold the returned client_unique_id,
$clientId = '';
setup your prepared statement
bind the parameter,
$statement->bind_param('s', $id)
do
{
generate a new Id. (Code for generating random id goes here).
$generatedId = '...';
// bind the generated id to the prepared statement.
$id = $generatedId
// execute the prepared statement,
$statement->execute()
// fetch the results into $clientId
$statement->bind_result($res);
while($statement->fetch()) {
$clientId = $res;
}
} while ($clientId != '');
$statement->close();
// echo the last generated Id
echo $generatedId;
cheers,
William
This is the login function written using MySQL way
However, the problem exists when it convert into PDO way
MYSQL:
<?
function confirmUser($username, $password){
global $conn;
if(!get_magic_quotes_gpc()) {
$username = addslashes($username);
}
/* Verify that user is in database */
$q = "select UserID,UserPW from user where UserID = '$username'";
$result = mysql_query($q,$conn);
if(!$result || (mysql_numrows($result) < 1)){
return 1; //Indicates username failure
}
/* Retrieve password from result, strip slashes */
$dbarray = mysql_fetch_array($result);
$dbarray['UserPW'] = stripslashes($dbarray['UserPW']);
$password = stripslashes($password);
/* Validate that password is correct */
if($password == $dbarray['UserPW']){
return 0; //Success! Username and password confirmed
}
else{
return 2; //Indicates password failure
}
}
PDO:
<?
function confirmUser($username, $password){
global $conn;
include("connection/conn.php");
$sql = '
SELECT COALESCE(id,0) is_row
FROM user
WHERE UserID = ?
LIMIT 1
';
$stmt = $conn->prepare($sql);
$stmt->execute(array('09185346d'));
$row = $stmt->fetch();
if ($row[0] > 0) {
$sql = '
SELECT COALESCE(id,1) is_row
FROM user
WHERE UserPW = ?
LIMIT 1
';
$stmt = $conn->prepare($sql);
$stmt->execute(array('asdasdsa'));
$row = $stmt->fetch();
if ($row[0] > 0)
return 2;
else
return 0;
}
elseif ($row[0] = 0)
{return 1;}
}
What is the problem ?? And is it necessary to include bind parameter in PDO??? THANKS
Aside from your use of global and your include inside the function (you should investigate an alternative way of structuring your function not to do this), I would change the code as follows:
$sql =
'SELECT id
FROM user
WHERE UserID = ?
AND UserPW = ?
LIMIT 1';
$stmt = $conn->prepare($sql);
$stmt->execute(array(
'09185346d',
'asdasdsa'
));
if ($stmt->rowCount() == 1) {
return 0;
}
else {
return 1;
}
Combing the queries to give a general Authentication error, instead of allowing people to trial valid usernames, and then valid passwords, and then using PDOStatements rowCount method do see if your row was returned.
To answer your second part, it is not necessary to specifically use bindParam to prevent SQL injection.
Here's a quick example of the difference between bindParam and bindValue
$param = 1;
$sql = 'SELECT id FROM myTable WHERE myValue = :param';
$stmt = $conn->prepare($sql);
Using bindParam
$stmt->bindParam(':param', $param);
$param = 2;
$stmt->execute();
SELECT id FROM myTable WHERE myValue = '2'
Using bindValue
$stmt->bindValue(':param', $param);
$param = 2;
$stmt->execute();
SELECT id FROM myTable WHERE myValue = '1'