David Garcia
David Garcia

Reputation: 2696

One-line PHP random string generator?

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

Upvotes: 40

Views: 78403

Answers (18)

RayJ
RayJ

Reputation: 742

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)));

Upvotes: 1

Peter O.
Peter O.

Reputation: 32878

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.

Upvotes: 1

Uours
Uours

Reputation: 2492

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 );

Upvotes: 30

EllisGL
EllisGL

Reputation: 125

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, '.')));

Upvotes: 1

user985366
user985366

Reputation: 1699

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

Upvotes: 1

Salar
Salar

Reputation: 5499

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;
}

Upvotes: 1

Bex
Bex

Reputation: 2925

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".

Upvotes: 1

Saud Khan
Saud Khan

Reputation: 844

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;
  }

Upvotes: 3

PavelŠ
PavelŠ

Reputation: 11

This function returns random lowercase string:

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

Upvotes: 1

Vipin Kumar R. Jaiswar
Vipin Kumar R. Jaiswar

Reputation: 741

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

Upvotes: 1

Charles
Charles

Reputation: 1128

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.

Upvotes: 1

Rudie
Rudie

Reputation: 53781

Creates a 200 char long hexdec string:

$string = bin2hex(openssl_random_pseudo_bytes(100));

maaarghk's answer is better though.

Upvotes: 4

maaarghk
maaarghk

Reputation: 347

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.

Upvotes: 6

Daniel Reyes
Daniel Reyes

Reputation: 297

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

Upvotes: 3

23k
23k

Reputation: 647

I had found something like this:

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

Upvotes: 30

Emilio Gort
Emilio Gort

Reputation: 3470

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;
  }

Upvotes: 2

RobAtStackOverflow
RobAtStackOverflow

Reputation: 525

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()));
?>

Upvotes: 2

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;

Upvotes: 6

Related Questions