40

I am looking for the shortest way to generate random/unique strings and for that I was using the following two:

$cClass = sha1(time());

or

$cClass = md5(time());

However, I need the string to begin with a letter, I was looking at base64 encoding but that adds == at the end and then I would need to get rid of that.

What would be the best way to achieve this with one line of code?


Update:

PRNDL came up with a good suggestions which I ended up using it but a bit modified

echo substr(str_shuffle(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ),0, 1) . substr(str_shuffle(aBcEeFgHiJkLmNoPqRstUvWxYz0123456789),0, 31)

Would yield 32 characters mimicking the md5 hash but it would always product the first char an alphabet letter, like so;

solution 1

However, Uours really improved upon and his answer;

substr(str_shuffle("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 1).substr(md5(time()),1);

is shorter and sweeter

The other suggestion by Anonymous2011 was very awesome but the first character for some reason would always either M, N, Y, Z so didn't fit my purposes but would have been the chosen answer, by the way does anyone know why it would always yield those particular letters?

Here is the preview of my modified version

echo  rtrim(base64_encode(md5(microtime())),"=");

runner up

5
  • 17
    Why does it need to be achieved within one line of code? Commented Sep 26, 2013 at 1:12
  • If you guys are wondering why the first letter, well I am doing some testing with div elements... classes or ids do not accept numbers on the first character and they dont accept special character anywhere Commented Sep 26, 2013 at 1:36
  • Prefix those with an underscore _0000 works. Commented Sep 26, 2013 at 1:52
  • "_0000".sha1(time()); - prefix via simple string concatenation Commented Sep 26, 2013 at 2:06
  • From 2010: PHP random string generator Commented Dec 5, 2023 at 1:52

18 Answers 18

30

Rather than shuffling the alphabet string , it is quicker to get a single random char .

Get a single random char from the string and then append the md5( time( ) ) to it . Before appending md5( time( ) ) remove one char from it so as to keep the resulting string length to 32 chars :

substr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", mt_rand(0, 51), 1).substr(md5(time()), 1);

Lowercase version :

substr("abcdefghijklmnopqrstuvwxyz", mt_rand(0, 25), 1).substr(md5(time()), 1);

Or even shorter and a tiny bit faster lowercase version :

chr(mt_rand(97, 122)).substr(md5(time()), 1);

/* or */

chr(mt_rand(ord('a'), ord('z'))).substr(md5(time()), 1);


A note to anyone trying to generate many random strings within a second:
Since
time( ) returns time in seconds , md5( time( ) ) will be same throughout a given second-of-time due to which if many random strings were generated within a second-of-time, those probably could end up having some duplicates .


I have tested using below code . This tests lower case version :

    $num_of_tests = 100000;

    $correct = $incorrect = 0;

    for( $i = 0; $i < $num_of_tests; $i++ )
    {
        $rand_str = substr( "abcdefghijklmnopqrstuvwxyz" ,mt_rand( 0 ,25 ) ,1 ) .substr( md5( time( ) ) ,1 );

        $first_char_of_rand_str = substr( $rand_str ,0 ,1 );

        if( ord( $first_char_of_rand_str ) < ord( 'a' ) or ord( $first_char_of_rand_str ) > ord( 'z' ) )
        {
            $incorrect++;
            echo $rand_str ,'<br>';
        }
        else
        {
            $correct++;
        }
    }

    echo 'Correct: ' ,$correct ,' . Incorrect: ' ,$incorrect ,' . Total: ' ,( $correct + $incorrect );
Sign up to request clarification or add additional context in comments.

7 Comments

Is there a probability that the first is ever a number? i executed the it about 50 times and got a number as first character but happened once 30128fb9b80c5697a4a3954b96e1295
I cannot see any reason except if the values in the mt_rand are not correct . I think it should be mt_rand(0, 50) . It was mt_rand(0, 51) previously .
Perhaps you are right, the first char is 0, I will now only use lower case chars, since the alphabet has 26 letters then the max param should be 25
With my corrected solution I have generated 100,000 strings and none of those started with numeric character . I have tested the lowercase solution for 100,000 strings and the solution seemed perfect .
Awesome, what did you use to generate the strings, also, just wondering how to benchmark my self the performance of these codes? any advice would be awesome
|
30

I had found something like this:

$length = 10;
$randomString = substr(str_shuffle(md5(time())),0,$length);
echo $randomString;

1 Comment

This is better version than the one above, as it is aways unique and has char lenght in it.
7

I decided this question needs a better answer. Like code golf! This also uses a better random byte generator.

preg_replace("/[\/=+]/", "", base64_encode(openssl_random_pseudo_bytes(8)));

Increase the number of bytes for a longer password, obviously.

1 Comment

You could use str_replace(array('/', '=', '+'), '', ..., that might be faster.
6

If you need it to start with a letter, you could do this. It's messy... but it's one line.

$randomString = substr(str_shuffle("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 1) . substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 10);

echo $randomString;

11 Comments

He never said it needed to be alfanumeric.
@Alix Axel: what do you actually mean?
You don't need the second str_shuffle.
actually it can be alphanumeric, however the first character needs to be an alphabet letter]
@Alix Axel: there won't be numbers then in the left part of string. OP expects it to be alpha-numeric except of the first character. That's obvious from base64 part of the question.
|
4

Creates a 200 char long hexdec string:

$string = bin2hex(openssl_random_pseudo_bytes(100));

maaarghk's answer is better though.

Comments

3

base_convert(microtime(true), 10, 36);

1 Comment

Please share more details. Which parts of that snippet provide randomness?
3

You can try this:

 function KeyGenerator($uid) {
    $tmp = '';
    for($z=0;$z<5;$z++) {
      $tmp .= chr(rand(97,122)) . rand(0,100);
    }
    $tmp .= $uid;
    return $tmp;
  }

Comments

2

I have generated this code for you. Simple, short and (resonably) elegant.

This uses the base64 as you mentioned, if length is not important to you - However it removes the "==" using str_replace.

<?php
        echo  str_ireplace("==", "", base64_encode(time()));
?>

4 Comments

Meh, use rtrim() instead!
I agree use rtrim(), also the last I checked == did not have uppercase and lowercase versions. So why use case-insensitive replacement?
I never knew about rtrim() - I will take this into account for the future, thanks! As for case insensitive, thats habit.
Please share more details. Which parts of that snippet provide randomness?
2

I use this function

usage:

 echo randomString(20, TRUE, TRUE, FALSE);

  /**
   * Generate Random String
   * @param Int Length of string(50)
   * @param Bool Upper Case(True,False)
   * @param Bool Numbers(True,False)
   * @param Bool Special Chars(True,False)
   * @return String  Random String
   */
  function randomString($length, $uc, $n, $sc) {
      $rstr='';
      $source = 'abcdefghijklmnopqrstuvwxyz';
      if ($uc)
          $source .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
      if ($n)
          $source .= '1234567890';
      if ($sc)
          $source .= '|@#~$%()=^*+[]{}-_';
      if ($length > 0) {
          $rstr = "";
          $length1= $length-1;
          $input=array('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')  
          $rand = array_rand($input, 1)
          $source = str_split($source, 1);
          for ($i = 1; $i <= $length1; $i++) {
              $num = mt_rand(1, count($source));
              $rstr1 .= $source[$num - 1];
              $rstr = "{$rand}{$rstr1}";
          }
      }
      return $rstr;
  }

23 Comments

$uc == 1, $n == 1 :-S
@zerkms 1 is true, 0 is false
echo improve(constant(Alix),True); --- it throws a MayBeAnotherDay exception :-(
@JoseDavidGarciaLlanos: OP = Original Poster = YOU. =)
@EmilioGort: I never said it needed to be. You can just drop it.
|
1

I'm using this one to generate dozens of unique strings in a single go, without repeating them, based on other good examples above:

$string = chr(mt_rand(97, 122))
          . substr(md5(str_shuffle(time() . rand(0, 999999))), 1);

This way, I was able to generate 1.000.000 unique strings in ~5 seconds. It's not THAT fast, I know, but as I just need a handful of them, I'm ok with it. By the way, generating 10 strings took less than 0.0001 ms.

Comments

1

JavaScript Solution:

function randomString(pIntLenght) {  
  var strChars = “0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz”;
  var strRandomstring = ”;

  for (var intCounterForLoop=0; intCounterForLoop < pIntLenght; intCounterForLoop++) {
      var rnum = Math.floor(Math.random() * strChars.length);
      strRandomstring += strChars.substring(rnum,rnum+1);
  }
   return strRandomstring;
}

alert(randomString(20));

Reference URL : Generate random string using JavaScript

PHP Solution:

function getRandomString($pIntLength = 30) {
      $strAlphaNumericString     = ’0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;

      $strReturnString         = ”;

      for ($intCounter = 0; $intCounter < $pIntLength; $intCounter++) {
           $strReturnString .= $strAlphaNumericString[rand(0, strlen($strAlphaNumericString) - 1)];
      }
      return $strReturnString;
}

echo getRandomString(20);

Reference URL : Generate random String using PHP

Comments

1

This function returns random lowercase string:

function randomstring($len=10){
 $randstr='';
 for($iii=1; $iii<=$len; $iii++){$randstr.=chr(rand(97,122));};
 return($randstr);
};

Comments

1

I find that base64 encoding is useful for creating random strings, and use this line:

base64_encode(openssl_random_pseudo_bytes(9));

It gives me a random string of 12 positions, with the additional benefit that the randomness is "cryptographically strong".

Comments

1

to generate strings consists of random characters, you can use this function

public function generate_random_name_for_file($length=50){
    $key = '';
    $keys = array_merge(range(0, 9), range('a', 'z'));
    for ($i = 0; $i < $length; $i++) {
        $key .= $keys[array_rand($keys)];
    }
    return $key;
}

Comments

1

It really depends on your requirements.

I needed strings to be unique between test runs, but not many other restrictions.

I also needed my string to start with a character, and this was good enough for my purpose.

$mystring = "/a" . microtime(true);

Example output:

a1511953584.0997

4 Comments

microtime does not use any random parts, and starting with a fixed letter doesn't provide any more randomness
@NicoHaase I didn't claim either of those two things, so not sure why you comment on this (and downvote?)
What do you mean by "I didn't claim either of those two things"? That's what the whole question is about: generating a random string
The question starts with to generate random/unique strings and in my case, just as for the OP (probably), being unique between function calls is good enough, it doesn't need to be truly random. They also write I need the string to begin with a letter without specifying randomness requirements for the letter itself. Since I had a use case of my own with similar requirements, which worked, I posted that.
1

How to match the OPs original request in an awful way (expanded for readability):

// [0-9] ASCII DEC 48-57
// [A-Z] ASCII DEC 65-90
// [a-z] ASCII DEC 97-122
// Generate: [A-Za-z][0-9A-Za-z]
$r = implode("", array_merge(array_map(function($a)
                             {
                                 $a = [rand(65, 90), rand(97, 122)];
                                 return chr($a[array_rand($a)]);
                             }, array_fill(0, 1, '.')),
                             array_map(function($a)
                             {
                                 $a = [rand(48, 57), rand(65, 90), rand(97, 122)];
                                 return chr($a[array_rand($a)]);
                             }, array_fill(0, 7, '.'))));

One the last array_fill() would would change the '7' to your length - 1.

For one that does all alpha-nurmeric (And still slow):

// [0-9A-Za-z]
$x = implode("", array_map(function($a)
                           {
                               $a = [rand(48, 57), rand(65, 90), rand(97, 122)];
                               return chr($a[array_rand($a)]);
                           }, array_fill(0, 8, '.')));

Comments

1

The following one-liner meets the requirements in your question: notably, it begins with a letter.

substr("abcdefghijklmnop",random_int(0, 16),1) . bin2hex(random_bytes(15))

If you didn't care whether the string begins with a letter, you could just use:

bin2hex(random_bytes(16))

Note that here we use random_bytes and random_int, which were introduced in PHP 7 and use cryptographic random generators, something that is important if you want unique strings to be hard to guess. Many other solutions, including those involving time(), microtime(), uniqid(), rand(), mt_rand(), str_shuffle(), array_rand(), and shuffle(), are much more predictable and are unsuitable if the random string will serve as a password, a bearer credential, a nonce, a session identifier, a "verification code" or "confirmation code", or another secret value.

I also list other things to keep in mind when generating unique identifiers, especially random ones.

Comments

1

True one liner random string options:

implode('', array_rand(array_flip(str_split(str_shuffle('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'))), 21));

md5(microtime() . implode('', array_rand(array_flip(str_split(str_shuffle('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'))), 21)));

sha1(microtime() . implode('', array_rand(array_flip(str_split(str_shuffle('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'))), 21)));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.