I'm generating a unique 5 digit code using the following.
$randomUniqueNumber = rand(10000,99999);
I need to change this to an alphanumeric number with 5 digits and 2 letters.
The below gives me an alphanumeric number, but not restricted to just 2 letters.
$generated = substr(md5(rand()),0,5);
How would I generate a random string with 5 digits, and two letters?
There are probably a few ways to do it, but the following is verbose to get you going.
<?php
// define your set
$nums = range(0, 9);
$alphas = range('a', 'z');
// shuffle sets
shuffle($nums);
shuffle($alphas);
// pick out only what you need
$nums = array_slice($nums, 0, 5);
$alphas = array_slice($alphas, 0, 2);
// merge them together
$set = array_merge($nums, $alphas);
// shuffle
shuffle($set);
// create your result
echo implode($set); //86m709g
https://3v4l.org/CV7fS
Edit:
After reading I'm generating a unique 5 digit code using the following. I suggest, instead, create your string by changing the base from an incremented value, rather than random (or shuffled) as you will undoubtedly get duplicates, and to achieve no dupes you would need to pre-generate and store your entire set of codes and pick from them.
Instead look at something like hashids.
Related
I'm trying to use CodeIgniter to write up a small program for school which generates a random 'key' every time I click the 'generate' button. Looking to see if there's a way for me to create a function where I can fill up a 14 character array with a random number or letter and then set the array to a variable which I can call upon to display as my generated key.
Any and all help would be much appreciated as I am new to CodeIgniter.
A while back I wrote this function in PHP, it does what it does and gives you some flexibility as well through complexity modifiers, I used a default set of 5 different 'levels' of characters and the length is also variable ofcourse.
I'm just going to chuck it in here and 'try' to explain what is going on as well as I can by comments:
function rsg($length = 10, $complexity = 2) {
//available 'complexity' subsets of characters
$charSubSets = array(
'abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'0123456789',
'!##$%^&*()_+{}|:">?<[]\\\';,.`~',
'µñ©æáßðøäåé®þüúíóö'
);
// will be filled with subsets from above $charSubsets
$chars = '';
//concact each subset until complexity is reached onto the $chars variable
for ($i = 0; $i < $complexity; $i++)
$chars .= $charSubSets[$i];
//create array containing a single char per entry from the combined subset in the $chars variable.
$chars = str_split($chars);
//define length of array for mt_rand limit
$charCount = (count($chars) - 1);
//create string to return
$string = '';
//idk why I used a while but it won't really hurt you when the string is less than 100000 chars long ;)
$i = 0;
while ($i < $length) {
$randomNumber = mt_rand(0, $charCount); //generate number within array index range
$string .= $chars[$randomNumber]; //get that character out of the array
$i++; //increment counter
}
return $string; //return string created from random characters
}
This is what I currently use and it has satisfied my needs for quite some time now, if anyone reading over this has improvements I'd love to hear them as well!
$a=array(rand(10000000000000, 99999999999999));
is a quick way to get a 14 digit array.
It depends on how random you want it to be. You could specify all characters you want in a $characters string, then just create a string up to $length, picking a random substring of length 1 from the characters string.
What are the requirements?
Do you want it to be as random as possible (This link might be useful)
Are multiple occurrences of one character allowed in one random string?
Here's an example though: PHP random string generator
I wonder if there is a way in PHP to generate a unique alphanumeric(case sensitive) tokens that can be unique forever without any collision. If we derive them from the time stamp string which is 10 characters like: 1394452319, that might be possible but I am not sure if we can make the token short up to 4 characters? If not possible then 5, 6, 7 and max is 8 characters. Because I want to generate short tokens to be readable by users.
Tokens should look like: 1aYc, ZoXq, 3iU9, etc.
I don't want to show the users any sequence.
One more thing, my application will be used by more than one user, so in case two users clicked at same time to generate the token, will the PHP application generate the same token (I assume we use the timestamp to generate the token)? How can we prevent from this problem?
Thank you for your help!
this is the another function that you can use also
<?php
function generateRandomString($length = 8) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
return $randomString;
}
echo generateRandomString();
?>
One approach is to have an incremental (i.e. auto_update) id that you keep hidden internally. From that, you generate a hash, representing the id to hide the sequence. The incremented id gets rid of collision problems (i.e. MySQL has an integrated solution for this).
The trick you need to use now is a random hash table consinsting of two columns, both having the values n to m but with the second column being randomized. i.e.
col1 | col2
1 | 2
2 | 4
3 | 5
4 | 1
5 | 3
if you have the randomly sorted number for your incremented number, it is easy to create a hash from that. Just think about your possible chars as numbers. You get it righgt?
Assuming you have a good algorithm for random numbers, you can make a pretty good hash table. However, there also is a way to find an algorithm, providing you with the numbers as they increase. So in this example it would give you col2 = fn(col1) so i.e. 4 = fn(2).
All you have to do is take the result and re-enginer it into a formular :D
Otherwise you have to fill the table initially.
To give you a glimpse insight into the math of it, think of a function that uses odd/even characteristics of the number and combines it with addition.
With n digits using a range of 62 possibilitys (case sensitive letters and numbers) per char you have 62^n possibilities.
For 4 digits that makes 14776336 possibilities (62^4).
Thou that might sound just wonderfull, you can imagine that having a table, prefilled with 14776336 id's is not the cleanest solution.
Still, i hope this at least leads into the right direction.
EDIT:
We started a discussion on math.stackexchange.com. IT has some additional information on how to create a function for our needs.
You can use something like following
<?php
// chars
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!##$%^&*()-+';
// convert to array
$arr = str_split($chars, 1);
// shuffle the array
shuffle($arr);
// array to chars with 8 chars
echo substr(implode('', $arr), 0, 8);
?>
You can use this function :
// RETRUN 24 digit of UNIX ID :
public function getComplexIDTicket(){ // duplicate method on Rest.php
$arrAZ1 = range('A','Z');
$arrAZ2 = range('A','Z');
$arrAZ3 = range('A','Z');
$arrs1 = range('A','Z');
$arrs2 = range('A','Z');
$arrs3 = range('A','Z');
$a1 = $arrAZ1[rand(0,25)];
$a2 = $arrAZ2[rand(0,25)];
$a3 = $arrAZ3[rand(0,25)];
$s1 = $arrs1[rand(0,25)];
$s2 = $arrs2[rand(0,25)];
$s3 = $arrs3[rand(0,25)];
$s = $s1.$s2.$s3;
$t = microtime(true);
$micro = sprintf("%07d",($t - floor($t)) * 10000000);
$id = date('ymdHis').strtoupper(dechex(substr($micro,0,7)));
$id = str_pad($id, 24, $a3.$a2.$a1.$s, STR_PAD_RIGHT);
// 151106214010 3DDBF0 L D C SM4
return $id;
}
Basically I have a script that allows members to register, passwords currently must contain at least 1 lower-case, 1 upper-case, 1 numeric and 1 special character, the password must also be at least 8 characters in length.
On the registration and password change pages I want to suggest 3 randomly generated strong passwords but not sure if my methods are the best way of doing it.
basically i run substr(str_shuffle()); against 4 set of characters, the first is lower case, the second is upper case, the third is numeric and the fourth is special characters.
Certain letters/numbers have been ommitted such as zero and O to avoid confusion between the 2. I have also repeated each character to allow for the option of each character to be included more than once.
I then do a final substr(str_shuffle()) on the output of the first 4 results to generate a password that is 10 characters in length and contains at least 2 of each of lower-case, upper-case, numeric and special characters.
// Generates a secure random password
$random_LC = substr(str_shuffle("abcdefghjkmnpqrstuvwxyzabcdefghjkmnpqrstuvwxyz"), 0, 2);
$random_UC = substr(str_shuffle("ABCDEFGHJKLMNPQRSTUVWXYZABCDEFGHJKLMNPQRSTUVWXYZ"), 0, 2);
$random_NC = substr(str_shuffle("2345678923456789"), 0, 2);
$random_SC = substr(str_shuffle("#~#[]{}+&*%()£$\/<>#~#[]{}+&*%()£$\/<>"), 0, 4);
$random_PW = substr(str_shuffle("$random_LC$random_UC$random_NC$random_SC"), 0, 10);
$random_PW2 = substr(str_shuffle("$random_LC$random_UC$random_NC$random_SC"), 0, 10);
$random_PW3 = substr(str_shuffle("$random_LC$random_UC$random_NC$random_SC"), 0, 10);
The output could then be echoed through $random_PW, $random_PW2 etc.
A current example of what the above code outputs is
vH}[2p$W2&
5$/wM6q(\P
qM5w6/$\P(
$PM\/65w(q
I believe that if i simply did 1 substr(str_shuffle()) against all the characters there is a good chance that it would not meet the requirements of at least 1 of each character type being included in the output.
Is there an easier way to produce a random password that meets the above requirements?
I'd suggest also varying the length of the password.
Probably it would be better not to have a constant number of special characters, lower case letters, uppercase and numbers. You could make sure that you have at least one of these and generate a random variation of mixed characters.
Here's an improved version (that generates a password between 8 and 12 characters and meets the criteria that you required):
$chr = array_merge(
range('A', 'N'), range('P', 'Z'),
range('a', 'n'), range('p', 'z'),
range(2, 9), str_split('#~#[]{}+&*%()£$\/<>')
);
$password = $chr[mt_rand(0, 24)] . $chr[mt_rand(25, 49)]
. $chr[mt_rand(50, 57)] . $chr[mt_rand(58, 76)];
for ($i = rand(4, 8); $i >= 0; $i--) {
$password .= $chr[mt_rand(0, count($chr) - 1)];
}
$password = str_shuffle($password);
How can I separate a number and get the first two digits in PHP?
For example: 1345 -> I want this output=> 13 or 1542 I want 15.
one possibility would be to use substr:
echo substr($mynumber, 0, 2);
EDIT:
please not that, like hakre said, this will break for negative numbers or small numbers with decimal places. his solution is the better one, as he's doing some checks to avoid this.
First of all you need to normalize your number, because not all numbers in PHP consist of digits only. You might be looking for an integer number:
$number = (int) $number;
Problems you can run in here is the range of integer numbers in PHP or rounding issues, see Integers Docs, INF comes to mind as well.
As the number now is an integer, you can use it in string context and extract the first two characters which will be the first two digits if the number is not negative. If the number is negative, the sign needs to be preserved:
$twoDigits = substr($number, 0, $number < 0 ? 3 : 2);
See the Demo.
Shouldn't be too hard? A simple substring should do the trick (you can treat numbers as strings in a loosely typed language like PHP).
See the PHP manual page for the substr() function.
Something like this:
$output = substr($input, 0, 2); //get first two characters (digits)
You can get the string value of your number then get the part you want using
substr.
this should do what you want
$length = 2;
$newstr = substr($string, $lenght);
With strong type-hinting in new version of PHP (> PHP 7.3) you can't use substr on a function if you have integer or float. Yes, you can cast as string but it's not a good solution.
You can divide by some ten factor and recast to int.
$number = 1345;
$mynumber = (int)($number/100);
echo $mynumber;
Display: 13
If you don't want to use substr you can divide your number by 10 until it has 2 digits:
<?php
function foo($i) {
$i = abs((int)$i);
while ($i > 99)
$i = $i / 10;
return $i;
}
will give you first two digits
Is there is any way to avoid duplication in random number generation .
I want to create a random number for a special purpose. But it's should be a unique value. I don't know how to avoid duplicate random number
ie, First i got the random number like 1892990070. i have created a folder named that random number(1892990070). My purpose is I will never get that number in future. I it so i have duplicate random number in my folder.
A random series of number can always have repeated numbers. You have to keep a record of which numbers are already used so you can regenerate the number if it's already used. Like this:
$used = array(); //Initialize the record array. This should only be done once.
//Do like this to draw a number:
do {
$random = rand(0, 2000);
}while(in_array($random, $used));
$used[] = $random; //Save $random into to $used array
My example above will of course only work across a single page load. If it should be static across page loads you'll have to use either sessions (for a single user) or some sort of database (if it should be unique to all users), but the logic is the same.
You can write a wrapper for mt_rand which remembers all the random number generated before.
function my_rand() {
static $seen = array();
do{
$rand = mt_rand();
}while(isset($seen[$rand]));
$seen[$rand] = 1;
return $rand;
}
The ideas to remember previously generated numbers and create new ones is a useful general solution when duplicates are a problem.
But are you sure an eventual duplicate is really a problem? Consider rolling dice. Sometimes they repeat the same value, even in two sequential throws. No one considers that a problem.
If you have a controlled need for a choosing random number—say like shuffling a deck of cards—there are several approaches. (I see there are several recently posted answer to that.)
Another approach is to use the numbers 0, 1, 2, ..., n and modify them in some way, like a Gray Code encoding or exclusive ORing by a constant bit pattern.
For what purpose are you generating the random number? If you are doing something that generates random "picks" of a finite set, like shuffling a deck of cards using a random-number function, then it's easiest to put the set into an array:
$set = array('one', 'two', 'three');
$random_set = array();
while (count($set)) {
# generate a random index into $set
$picked_idx = random(0, count($set) - 1);
# copy the value out
$random_set []= $set[$picked_idx];
# remove the value from the original set
array_splice($set, $picked_idx, 1);
}
If you are generating unique keys for things, you may need to hash them:
# hold onto the random values we've picked
$already_picked = array();
do {
$new_pick = rand();
# loop until we know we don't have a value that's been picked before
} while (array_key_exists($new_pick, $already_picked));
$already_picked[$new_pick] = 1;
This will generate a string with one occurence of each digit:
$randomcharacters = '0123456789';
$length = 5;
$newcharacters = str_shuffle($randomcharacters);
$randomstring = substr($newcharacters, 0, $length);