1003

I'm trying to create a randomized string in PHP, and I get absolutely no output with this:

<?php
    function RandomString()
    {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $randstring = '';
        for ($i = 0; $i < 10; $i++) {
            $randstring = $characters[rand(0, strlen($characters))];
        }
        return $randstring;
    }

    RandomString();
    echo $randstring;

What am I doing wrong?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Captain Lightning
  • 10,493
  • 4
  • 19
  • 17
  • 302
    My one line solution for generate short string is substr(md5(rand()), 0, 7); good luck ... – tasmaniski Jun 21 '12 at 14:46
  • 7
    @tasmaniski.. Your solution is ok.. But its less randomized! In your example the number of random strings that can be generated is limited by the size of integer. ( 2^32 ) at the max.. In case of the other solution, you can generate ( 62^8 ).. In case, I want larger strings, then number of distinct strings remain at max 2^32, but in the other solution it increases to ( 62^n ).. – Manu Dec 23 '13 at 08:12
  • @tasmaniski: `printf("%08x", rand());` :) – spinkus Apr 03 '14 at 06:40
  • 12
    You forgot to add each new generated character to the string. You're just overwriting it as it is. Should be $randstring .= $characters.. – Spock Apr 25 '14 at 09:28
  • 1
    ^ this is the short and direct answer – thedjaney Jun 26 '15 at 02:13
  • 3
    @CaptainLightning Can you please swap out the accepted answer for one of the more secure ones? :) – Scott Arciszewski Dec 08 '15 at 06:29
  • wondering why this question have 384 upvotes. – vivex May 23 '16 at 11:31
  • 1
    calling function and printing another variable, Do like this : function RandomString() { $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $randstring = ''; for ($i = 0; $i < 10; $i++) { $randstring .= $characters[rand(0, strlen($characters))]; } return $randstring; } echo RandomString(); – Ashish Patel Jul 01 '16 at 09:09
  • 3
    `strlen($characters)` => `strlen($characters) - 1` - string length starts with 1 – Zippp Apr 24 '17 at 13:07
  • 1
    @tasmaniski, it should be `mt_rand()` instead of `rand()`. – Oleg Abrazhaev Jul 26 '17 at 14:43
  • Simple command: `php -r "echo sha1(rand());"` – insign Mar 14 '18 at 01:25
  • 1
    Isn't 66 answers enough for this relatively simple question? – Peter Mortensen Jul 18 '19 at 14:09
  • Keep in mind that, existentially speaking, there is no such thing as a random number. God does not throw dice. I am not suggesting we not use the word "random". Only that when we do say "random, it is with the caveat that we understand there is no such thing as a random number, and that we are in fact referring to the "illusion" of randomness. –  Sep 15 '19 at 18:05
  • 1
    yet another solution `echo random_bytes(len)`[random_bytes](https://www.php.net/random_bytes) – 8ctopus Nov 19 '20 at 09:15

69 Answers69

1644

To answer this question specifically, two problems:

  1. $randstring is not in scope when you echo it.
  2. The characters are not getting concatenated together in the loop.

Here's a code snippet with the corrections:

function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[random_int(0, $charactersLength - 1)];
    }
    return $randomString;
}

Output the random string with the call below:

// Echo the random string.
// Optionally, you can give it a desired string length.
echo generateRandomString();

Please note that previous version of this answer used rand() instead of random_int() and therefore generated predictable random strings. So it was changed to be more secure, following advice from this answer.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
Stephen Watkins
  • 25,047
  • 15
  • 66
  • 100
  • Your update is weird, this is a random generation but no char can be used more than once. – AsTeR Jan 18 '13 at 15:56
  • 2
    Why wasting that extra variable, `$i`? Just do `for ($randomString = ''; strlen($STR) < 50;) $randomString .= $characters[rand(0, strlen($characters) - 1)];` instead of your loop, or simplified, `for ($STR = ''; strlen($STR) < 50;) $STR .= $CHR[rand(0, strlen($CHR) - 1)];` – Francisco Presencia May 25 '13 at 04:22
  • 36
    @FranciscoPresencia, It's better "wasting" an extra variable as of calling an method in the compare condition of an loop. – Rico Sonntag Aug 16 '13 at 08:58
  • 246
    All that work, why not just something like `substr(str_shuffle(MD5(microtime())), 0, 10);`? – SpYk3HH Apr 09 '14 at 13:06
  • 1
    @SpYk3HH that's spot on, no duplicates at all using this. Brain child! – ᴍᴀᴛᴛ ʙᴀᴋᴇʀ Jun 18 '14 at 08:55
  • 7
    Thanks for the code, but please change `rand()` to `mt_rand()`. I used your method and experienced a *ton* of collisions with names. – Nate Jul 25 '14 at 00:34
  • 2
    @MatthewT.Baker wouldn't you *want* duplicates in a random string? If no character can be duplicated, you (significantly!) reduce the entropy in the generated string. – RonLugge Sep 09 '14 at 17:23
  • 2
    @RonLugge, I think you've misunderstood, I'm referring to the `MD5(microtime())` comment by @SpYk3HH. – ᴍᴀᴛᴛ ʙᴀᴋᴇʀ Sep 10 '14 at 09:24
  • 7
    @FranciscoPresencia do you have any idea how horrifically inefficient that is? You are checking the length of a string twice per iteration! The strlen inside the loop should be cached in a variable before entering the loop as well. – brettwhiteman Nov 29 '14 at 06:51
  • 2
    @SpYk3HH That will not have uppercase letters. – Pavel Bariev May 27 '15 at 08:39
  • 3
    @PavelBariev I suppose, if you must have some capitals, you could change it like so: implode('', array_map(function($i) { return rand(1, 10)%2 == 0 ? strtoupper($i) : $i; }, str_split(substr(str_shuffle(MD5(microtime())), 0, 10)))); [Blog](http://spyk3lc.blogspot.com/2014/06/i-know-its-been-quite-while-and-i-need.html) – SpYk3HH May 27 '15 at 18:45
  • 6
    This is not a good solution. The strings this generates will be predictable. :( – Scott Arciszewski Jun 29 '15 at 03:45
  • Why does this cause the string length to change with random characters: $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+-={}|[]:";<>?,./'; – a coder Jul 19 '15 at 04:58
  • 1
    So, if you don't want to offend people you should likely remove all of the vowels. That way you will not be randomly creating bad words. – Nate Bunney May 19 '16 at 21:12
  • 2
    For pseudo random strings of length greater than 32 characters: `substr(str_shuffle(str_repeat(MD5(microtime()), ceil($len/32))), 0, $len)` – sudo Jun 03 '16 at 21:47
  • I am creating an online quiz that needs to generate random string to give a temporary id to multiple choices. does the predictability of this answer allow test participants to cheat? – swdmnd Jan 10 '20 at 08:07
  • Thanks for this snippet. It works for my use case as well. However, this solution produces errors with special characters like ä, ö, and ü. To solve this, we need to take multibyte strings into account (default encoding with UTF-8 assumed): replace `$charactersLength = strlen($characters);` with `$charactersLength = mb_strlen($characters)`, and within the `for` loop add a variable `$charPos = random_int(0, $charactersLength - 1);`. Then replace `$randomString .= $characters[random_int(0, $charactersLength - 1)];` with `$randomString .= mb_substr($characters, $charPos, 1);`. – CLN Mar 30 '23 at 07:59
433

Note: str_shuffle() internally uses rand(), which is unsuitable for cryptography purposes (e.g. generating random passwords). You want a secure random number generator instead. It also doesn't allow characters to repeat.

One more way.

UPDATED (now this generates any length of string):

function generateRandomString($length = 10) {
    return substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,$length);
}

echo  generateRandomString();  // OR: generateRandomString(24)

That's it. :)

Community
  • 1
  • 1
A. Cheshirov
  • 4,808
  • 1
  • 13
  • 13
  • 67
    +1 for the shortest answer :). But not the best answer for every use-case. This code will output strings where each character won't appear more than once (thus making it weaker for brute force attacks) and won't output anything longer than 62 characters. – David Dec 05 '12 at 09:55
  • 20
    Do not do this, it is extremely weak. The longer you make your random string, the weaker it will be. – Abhi Beckert Feb 13 '13 at 21:38
  • 28
    Weak it may be, but it's quick and easy. Depending on the use-case, this is fine -- I've used it because I didn't need security or strength; just a quick-fire shuffle. I'm writing a unit test, and this gives me a suitably random input to test with. – SDC Mar 12 '13 at 13:44
  • It could be even shorter if you use `range()`. – fracz Aug 01 '13 at 22:16
  • 1
    @AbhiBeckert , simply not true as shown in Wolfram Alpha: https://www.wolframalpha.com/input/?i=plot+62!+%2F+%2862+-+x%29!+from+55+to+62# (where x is the length of the password). It shows how 62 characters is as secure as 61, but for any other value from 0 to 61, the number of possibilities just grows. – Francisco Presencia Aug 09 '13 at 19:06
  • 25
    @FranciscoPresencia the reason it is not secure is because it never uses the same character twice. That makes it a _terrible_ password generator. Please everyone stop up voting this, it is totally insecure must never be used. As the password gets longer, the number of characters you must test in a brute force gets shorter because you do not bother testing any previously used character. – Abhi Beckert Aug 09 '13 at 19:33
  • 1
    I agree that the rate of growth of the security decreases (added combinations per each added character), but the global security is still increased (total possible combinations), as you can see in the link I posted. That equation I wrote takes into account that it never uses a character twice and still supports my words... Do you think the equation is wrong or have any mathematical argument besides your word? Note: if the range of characters (0-9a-zA-Z) was much smaller, like (0-6), I'd agree that it'd be different, but that's not the case. – Francisco Presencia Aug 09 '13 at 20:49
  • 1
    @francisco, your maths is spot on, but what's important is that if you allow characters to be repeated, and we're taking a 61 character password (since the 62nd adds nothing when you're just shuffling), then comparing 62^61 (allowing repeats) with 62! (shuffling) shows that allowing repeats gives you a password with 1.5*10^25 more combinations. That's a massive difference in security. https://www.wolframalpha.com/input/?i=61%5E62%2F62%21 – Peter Bagnall Nov 06 '13 at 14:19
  • 11
    @FranciscoPresencia: I support your comments about avoiding using this for random passwords. However, I disagree that this answer should not be plus-one'd. I have plus-one'd this option for since it is an effective one-line solution for generating random strings (the original topic of this question). – bwright Dec 06 '13 at 17:11
  • One can use str_repeat() to allow the same character multiple times: return substr(str_shuffle(str_repeat("characters", $length)), 0, $length); (But the original oneliner is really sufficient for any PRACTICAL use even without repeating characters.) – Rauli Rajande Mar 17 '15 at 11:36
  • What if i'm need exclude numbers? I need only letters – Oleg Abrazhaev Aug 10 '15 at 14:24
  • A handy and elegant way to generate a random string. I am not using it for security purposes, so this gets my +1 –  Dec 24 '15 at 05:04
  • **Answer updated.** Now it generates string with unlimited length. – T.Todua Jul 29 '16 at 17:23
  • I like this, simply because no one asked for a password secure random string, that is something that is insecure by itself so should not be done either way. – Tobias Hagenbeek Oct 17 '16 at 18:12
  • 1
    There was no mention of cryptography purposes in the question – JG Estiot Mar 29 '18 at 08:05
  • 1
    Note: OP never mentioned the context in which the string would be used. They simply asked for assistance in addressing an issue with generating a simple random string, so the question of security and efficiency for cryptographic purposes might be irrelevant to the OP's needs. – Lakitu May 15 '18 at 18:53
  • 1
    for more security you can use this change: return substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', $length)), 1, $length); – Mahoor13 May 08 '19 at 10:27
  • I searched for this for a bulk file renaming with no security needed whatsoever. This solution simply works. – Random Elephant Jul 24 '19 at 18:15
  • @Lakitu The OP should indeed clarify his use case, as it appears from the OP's question the OP is clearly doing something that requires cryptographic strength. If, however, the OP is selecting random playing cards for Black Jack, Poker, etc, then "stronger cryptographic randomness" could potentially result in less clustering (until the back of the deck), which would translate to "weaker randomness" for a deck of cards, etc, because the game player can then predict minimal clustering and adjust his strategy. In the OP's case, however, this does not appear to be the case. –  Sep 15 '19 at 18:45
  • You can instantly make this secure by duplicating the input string two, three, or four times which makes it possible to repeat characters. For example, if your character pool is "Abc", use "AbcAbcAbc" instead. – MonkeyBusiness Mar 15 '22 at 06:47
430

There are a lot of answers to this question, but none of them leverage a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG).

The simple, secure, and correct answer is to use RandomLib and don't reinvent the wheel.

For those of you who insist on inventing your own solution, PHP 7.0.0 will provide random_int() for this purpose; if you're still on PHP 5.x, we wrote a PHP 5 polyfill for random_int() so you can use the new API even before you upgrade to PHP 7.

Safely generating random integers in PHP isn't a trivial task. You should always check with your resident StackExchange cryptography experts before you deploy a home-grown algorithm in production.

With a secure integer generator in place, generating a random string with a CSPRNG is a walk in the park.

Creating a Secure, Random String

/**
 * Generate a random string, using a cryptographically secure 
 * pseudorandom number generator (random_int)
 *
 * This function uses type hints now (PHP 7+ only), but it was originally
 * written for PHP 5 as well.
 * 
 * For PHP 7, random_int is a PHP core function
 * For PHP 5.x, depends on https://github.com/paragonie/random_compat
 * 
 * @param int $length      How many characters do we want?
 * @param string $keyspace A string of all possible characters
 *                         to select from
 * @return string
 */
function random_str(
    int $length = 64,
    string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
): string {
    if ($length < 1) {
        throw new \RangeException("Length must be a positive integer");
    }
    $pieces = [];
    $max = mb_strlen($keyspace, '8bit') - 1;
    for ($i = 0; $i < $length; ++$i) {
        $pieces []= $keyspace[random_int(0, $max)];
    }
    return implode('', $pieces);
}

Usage:

$a = random_str(32);
$b = random_str(8, 'abcdefghijklmnopqrstuvwxyz');
$c = random_str();

Demo: https://3v4l.org/IMJGF (Ignore the PHP 5 failures; it needs random_compat)

Scott Arciszewski
  • 33,610
  • 16
  • 89
  • 206
  • 3
    At the beginning of the function add `$keyspace = str_shuffle($keyspace );` for more security – Jevgenij Dmitrijev Apr 16 '17 at 19:17
  • 24
    What do you mean by "for more security"? We're already using a secure random number generator. – Scott Arciszewski Apr 17 '17 at 13:49
  • Notice: The "RandomLib" is no more supported, from I see. It has last commit from about 11 months (from now) and problems with PHP 7.1: https://github.com/ircmaxell/RandomLib/issues/55 Someone from this issue suggested to use `openssl_random_pseudo_bytes()`. – Jazi Aug 08 '17 at 12:08
  • @KrzysztofTrzos Would you mind posting an updated version which is fixed with what you mentioned in your comment? – Magiranu Oct 29 '17 at 21:24
  • The question was not about cryptography – JG Estiot Mar 29 '18 at 08:05
  • 12
    @JGEstiot Creating securely random strings requires cryptographically secure randomness. Someone searching "how to generate random strings in PHP" is better served by a secure answer than an insecure answer. – Scott Arciszewski Mar 30 '18 at 13:47
  • 4
    @ Scott Arciszewski You do not need to create cryptographically random strings every time you create random strings. The question was about creating randomized strings and this has nothing to do with security. You assumed that the string is going to be used in a security-sensitive context and you add a layer of complexity that deters from the core of the question. – JG Estiot Mar 31 '18 at 19:57
  • 75
    Using `random_int()` instead of `rand()` or `mt_rand()` adds no complexity for the developer. At the same time, it gives them greater security. People who come to StackOverflow looking for quick solutions might not know if the thing they're building needs to be secure or not. If we give them secure-by-default answers, they create a more secure Internet even if, from their perspective, it's totally accidental. Why you would oppose this goal is a mystery to me. – Scott Arciszewski Apr 01 '18 at 20:21
  • Due to this function accept 2nd parameter (`$keyspace`) and you are using string index (`$string[12]` - for example) which is not support multi-byte or unicode characters. ( see https://www.php.net/manual/en/language.types.string.php#language.types.string.substr ) So, this would be good if it is able to check for ascii characters first using `if (strtolower(mb_detect_encoding($keyspace)) === 'ascii'`) otherwise it can random something like `'กขคงจฉช'` to `'���'`. – vee Jun 26 '19 at 16:38
  • Don't use it on multibyte strings. Write your own if you want that. – Scott Arciszewski Jun 28 '19 at 02:35
  • 1
    I would suggest a few minor improvements, to harden this function further and prevent it's mis-use. As the author rightly says, why not make it as good as possible for the copy and pasters! Add type declarations for the arguments (for PHP 7+ use of course), "int" and "string" respectively and return casting, "string". A strong default length, 64? Then add an error for the length being less than 1, which would result in a blank string. – Jamie Robinson Jul 30 '19 at 11:09
  • 1
    I am sure the OP knows this already, but it's worth mentioning: remove vowels to avoid generating some pretty fancy curse words, if you'll be sending this password in an email to your new customers / new registered users. –  Sep 15 '19 at 18:52
  • 2
    I really like your answer, but I question myself. Why do you use implode() at the end and not just append the new characters with a .= instead of adding them to an array? Is there a huge performance impact? – Kevin Glier Apr 28 '20 at 09:48
  • I wanted to echo @KevinGlier's question. Love this answer, but what's the purpose of constructing an array and them imploding it back into a string (which is basically already an array of characters anyway)? I assume there's good reason, I just don't understand it. – Chuck Le Butt Feb 26 '21 at 23:15
  • 1
    To answer my own question, even when generating 100,000 strings of various lengths, there is no performance impact that I could detect. You may as well change to a string if that feels more readable. – Chuck Le Butt Feb 26 '21 at 23:36
  • I was looking for an answer like yours. Thank you @scott-arciszewski! – Emil Viesná Oct 27 '22 at 12:35
214

This creates a 20 character long hexadecimal string:

$string = bin2hex(openssl_random_pseudo_bytes(10)); // 20 chars

In PHP 7 (random_bytes()):

$string = base64_encode(random_bytes(10)); // ~14 characters, includes /=+
// or
$string = substr(str_replace(['+', '/', '='], '', base64_encode(random_bytes(32))), 0, 32); // 32 characters, without /=+
// or
$string = bin2hex(random_bytes(10)); // 20 characters, only 0-9a-f
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rudie
  • 52,220
  • 42
  • 131
  • 173
  • 2
    Please note that `openssl_random_pseudo_bytes()` did not use a cryptographically strong algorithm until php 5.6. Related bug: https://bugs.php.net/bug.php?id=70014 – acidtv Aug 08 '16 at 15:30
  • Also note that the smallest string this can make is of length 2. If you pass a byte length of 1 or less to `openssl_random_pseudo_bytes()` you will get nothing back. Also, note that when using `bin2hex(openssl_random_pseudo_bytes($length / 2))` since you are working with integers, it will automatically remove the modulo and will use the next lowest multiple of 2. So, `$length = 19` will produce a string of length 18. – Nathan F. Oct 26 '16 at 21:56
  • Proposal to use it as file content that can be opened through `fgets($fp, 1024)` and every file editor that has problems with very long lines: `function string_rand($len, $split="\n") { return substr(chunk_split(bin2hex(openssl_random_pseudo_bytes(ceil($len / 2))), 1023, $split), 0, $len); }` Set `$split` to `null` if it should return a one-liner. By that you can use it for both cases. – mgutt Mar 27 '17 at 13:01
  • I really like the random_bytes solution for PHP 7, but if you need the string to be a certain number of characters would something like this work? `$string = substr(base64_encode(random_bytes($size)), 0, $size);` – Programster Nov 27 '17 at 11:04
  • This is absolutely without a doubt the best solution. Takes up very little space and is super easy to understand. – Matthew Campbell May 10 '18 at 17:37
  • Note that `base64_encode` uses the 62 alphanumeric characters plus `/` and `+`. Furthermore, `bin2hex` use only 16 alphanumeric characters, that may be not enough. So the better is to take a long random string, to base64 it, to remove `+` and `/`, and to substr the result: `$string = substr(str_replace(['+', '/', '-', '='], '', base64_encode(random_bytes(32))), 0, 16); // "always" 16 chars.` – Daniel-KM Nov 16 '18 at 17:51
  • @Daniel-KM I agree. That's how I always use it. I added it to the answer. – Rudie Nov 16 '18 at 21:39
  • Ha! What a nice surprise!: https://github.com/PHPMailer/PHPMailer/blob/a69cfb1860c36f607d0822ee88d8a67da35fa5d8/src/PHPMailer.php#L2753 – Artfaith Dec 24 '21 at 22:09
113

@tasmaniski: your answer worked for me. I had the same problem, and I would suggest it for those who are ever looking for the same answer. Here it is from @tasmaniski:

<?php 
    $random = substr(md5(mt_rand()), 0, 7);
    echo $random;
?>

Here is a youtube video showing us how to create a random number

Humphrey
  • 2,659
  • 3
  • 28
  • 38
  • 11
    if your string is based on only a random integer, why not just use the random integer? they haystack doesnt get any deeper by hashing it... and by cutting the hash of you actually deminish the little entropy you had to start with. – The Surrican Sep 13 '14 at 14:23
  • 4
    Keep in mind `md5` will result in a 30 character limit and always lowercase characters. – Will B. Nov 03 '14 at 15:12
  • 4
    Additionally, rand() shouldn't be used for cryptography. If you're looking to generate a crypographically sound string, use [openssl_random_pseudo_bytes](http://php.net/manual/en/function.openssl-random-pseudo-bytes.php). – mattkgross Feb 23 '15 at 04:44
  • `md5(rand())` only offers 2^32 possible values. This means after, on average, 2^16 random strings you will expect one to repeat. – Scott Arciszewski Jun 29 '15 at 03:45
  • 3
    Well..i would bet the OP is not talking about "securely random strings". This solution is compact, easy and pretty to remember, for the **right** use cases. And, if you need to take care of possible collisions, why not to prepend/append a timestamp to the random string? :) – Erenor Paz Dec 29 '16 at 14:10
  • A pseudo-random integer with a cycle of 2^16 or 2^32 fed into SHA-256 with a long secret salt creates an almost cryptographically secure value, even though there may only be 2^16 values possible. The reason is that without knowing the secret salt one cannot cycle through all 2^16 values. If there is no salt, then it is possible to cycle through all the integers in range 2^16 and try each value. – David Spector Jun 11 '21 at 22:43
  • Not Found The requested URL was not found on this server. Apache/2.4.51 (Unix) Server at t9155861.beget.tech Port 80 – Eugene Sermyagin Oct 14 '22 at 18:32
51

Depending on your application (I wanted to generate passwords), you could use

$string = base64_encode(openssl_random_pseudo_bytes(30));

Being base64, they may contain = or - as well as the requested characters. You could generate a longer string, then filter and trim it to remove those.

openssl_random_pseudo_bytes seems to be the recommended way way to generate a proper random number in php. Why rand doesn't use /dev/random I don't know.

rjmunro
  • 27,203
  • 20
  • 110
  • 132
  • 2
    rand doesn't use /dev/urandom because that is only available in posix like environments and is not portable. – MacroMan Mar 25 '14 at 09:22
  • 3
    @MacroMan But `openssl_random_pseudo_bytes()` *is* portable. – Ja͢ck Jul 29 '14 at 05:29
  • If you want to strip out the extra base64 characters, try this: https://gist.github.com/zyphlar/7217f566fc83a9633959 – willbradley Dec 20 '14 at 22:38
  • 4
    This isn't wrong, but I would advise caution in how you discard the unwanted characters. See [this pull request on the PHP league's OAuth2 Server](https://github.com/thephpleague/oauth2-server/pull/273), for example. – Scott Arciszewski Jul 06 '15 at 06:11
  • This is one of the best answers. Pity it doesn't have more support. I would recommend editing your answer for better handling of unwanted characters though. – jcuenod Aug 04 '16 at 18:32
  • I'm pretty sure the two characters you list are incorrect for most current base64 algorithms. Besides, base64 takes up more space than ordinary characters, which can be sanitized as desired. And if you have space to burn, use hexadecimal. It is always safe. – David Spector Jun 11 '21 at 22:47
  • Replace rather than discard. I will let the reader sort out why this is preferable. – Lloyd Sargent May 17 '23 at 19:54
36

PHP 7+ Generate cryptographically secure random bytes using random_bytes function.

$bytes = random_bytes(16);
echo bin2hex($bytes);

Possible output

da821217e61e33ed4b2dd96f8439056c


PHP 5.3+ Generate pseudo-random bytes using openssl_random_pseudo_bytes function.

$bytes = openssl_random_pseudo_bytes(16);
echo bin2hex($bytes);

Possible output

e2d1254506fbb6cd842cd640333214ad


The best use case could be

function getRandomBytes($length = 16)
{
    if (function_exists('random_bytes')) {
        $bytes = random_bytes($length / 2);
    } else {
        $bytes = openssl_random_pseudo_bytes($length / 2);
    }
    return bin2hex($bytes);
}
echo getRandomBytes();

Possible output

ba8cc342bdf91143

Madan Sapkota
  • 25,047
  • 11
  • 113
  • 117
  • 1
    This will not generate a string with the given length – Timberman Feb 19 '20 at 08:39
  • getRandomBytes() (all of them, really) only works for even lengths. Other than that, one of the better, less-scary answers here. – Dewi Morgan Sep 24 '21 at 06:07
  • @DewiMorgan, I guess any hashing algo generates even length. – Madan Sapkota Sep 25 '21 at 03:32
  • Well, it's more that bin2hex() specifically will inevitably return an even number of hex chars. Truncating the output by one char for odd-length cases shouldn't, *so far as I can tell*, affect the entropy... but I admit it'd add a few extra lines to the code that would be pointless for almost all use-cases. – Dewi Morgan Sep 25 '21 at 03:55
  • So $odd=$length%2; $length+=$odd; at the beginning, and return substr(bin2hex($length), $odd); at the end would do the trick... but at the cost of considerable readability. Yours is cleaner and more maintainable, so I'd probably just add a comment about the "only even lengths" caveat if I were to use it, unless it truly mattered. – Dewi Morgan Sep 25 '21 at 04:03
  • openssl_random_pseudo_bytes was slow on PHP < 5.3.4 Windows – Cody Tookode Sep 11 '22 at 04:44
  • @AlPo, if one still uses PHP < 5.3, they deserve the slowest performance. – Madan Sapkota Sep 11 '22 at 10:31
29

Here is a simple one-liner that generates a true random string without any script level looping or use of OpenSSL libraries.

echo substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', mt_rand(1,10))), 1, 10);

To break it down so the parameters are clear

// Character List to Pick from
$chrList = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

// Minimum/Maximum times to repeat character List to seed from
$chrRepeatMin = 1; // Minimum times to repeat the seed string
$chrRepeatMax = 10; // Maximum times to repeat the seed string

// Length of Random String returned
$chrRandomLength = 10;

// The ONE LINE random command with the above variables.
echo substr(str_shuffle(str_repeat($chrList, mt_rand($chrRepeatMin,$chrRepeatMax))), 1, $chrRandomLength);

This method works by randomly repeating the character list, then shuffles the combined string, and returns the number of characters specified.

You can further randomize this, by randomizing the length of the returned string, replacing $chrRandomLength with mt_rand(8, 15) (for a random string between 8 and 15 characters).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kraang Prime
  • 9,981
  • 10
  • 58
  • 124
  • sorry to say but when one character gots selected its probability of occuring again is not as high as the other characters still remaining in the pool. no true randomness here... – The Surrican Sep 13 '14 at 14:16
  • @TheSurrican - You would be incorrect in that statement. All characters have an equal probability using this algorithm, and thus is truly random. This is ensured by repeating the chrList string $chrRepeatMax, and the magic really happens in str_shuffle which determines the randomness. – Kraang Prime Apr 16 '15 at 08:56
  • All chars would appear only once and it is very prone to bruteforce guess – venimus Jul 20 '15 at 09:28
  • @venimus Thats incorrect. The char string is duplicated for as many characters as you want (see `$chrRepeatMax` and `$chrRepeatMin` ) -- so a 10 char string , could (unlikely, but possible), be "aaaaaaaaaa". – Kraang Prime Aug 03 '15 at 14:26
  • @SanuelJackson Sorry I miss-commented. I've put the comment on the wrong answer. You are right! I actually used your "trick", but didn't use mt_rand, because it is useless IMHO. It does not add to the entropy. Just used const with the max-length. – venimus Aug 04 '15 at 13:06
  • @venimus - The difference is speed : "The mt_rand() function is a drop-in replacement for the older rand(). It uses a random number generator with known characteristics using the » Mersenne Twister, which will produce random numbers four times faster than what the average libc rand() provides." – Kraang Prime Aug 26 '18 at 17:16
  • What I mean is that `str_shuffle` randomizes it anyway – venimus Aug 27 '18 at 06:58
  • 1
    This algorithm is clever, but it is based on mt_rand, which generates a deterministic sequence of numbers. The output can be decoded by obtaining or guessing the salt. A true random sequence cannot be decoded into something with less entropy, like a small integer, under any conditions. A good approximation to true randomness is achieved by some systems by generating real-world entropy through such means as measuring how long it takes a person to type or move a mouse. Note that using the system time is not truly random, either, since an attacker can sometimes intercept device timing signals. – David Spector Jun 11 '21 at 22:53
  • 1
    str_shuffle is deterministic, not truly random. – David Spector Jun 11 '21 at 22:56
  • 1
    Downvote reasons: 1) claims "a *true* random string" rather than "a *pseudo*random string" when mt_rand is not truly random; claims equal probability of character selection, which shows a misunderstanding of statistics. Once the first character is selected from the string, the probability of it's selection for the second is then 9/(10*n) while all other characters are 10/(10*n). This stuff matters: such errors are dangerous in a security context. – Dewi Morgan Sep 24 '21 at 06:01
26

A better way to implement this function is:

function RandomString($length) {
    $keys = array_merge(range(0,9), range('a', 'z'));

    $key = "";
    for($i=0; $i < $length; $i++) {
        $key .= $keys[mt_rand(0, count($keys) - 1)];
    }
    return $key;
}

echo RandomString(20);

mt_rand is more random according to this and this in PHP 7. The rand function is an alias of mt_rand.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 1
    Caution: `mt_rand` does not generate cryptographically secure values. For that you should use PHP7's `random_int` or `random_bytes`. – jchook Mar 20 '18 at 13:12
25
function generateRandomString($length = 15)
{
    return substr(sha1(rand()), 0, $length);
}

Tada!

Davor
  • 1,387
  • 16
  • 33
  • Keep in mind `sha1` will result in a 40 character limit and always lowercase characters. – Will B. Nov 03 '14 at 15:11
  • 3
    sha1 strings are not random, certain characters will occur more frequently than others. It would be unwise to use this in cases where you genuinely want randomness like for passwords. – Kit Sunde Nov 11 '14 at 12:55
  • 2
    @KitSunde - yes, sha isn't random, rand() is random. And sha is perfectly fine for what is needed here. OP doesn't need crypto level of randomness. – Davor Oct 09 '15 at 12:52
  • @Davor `rant()` being random doesn't matter when sha isn't evenly distributed. If you randomly select from an uneven distribution you get the exact same uneven distribution. It's not "crypto level" randomness I'm highlighting, if that was the case you shouldn't be using `rand()` either. It takes minimal effort to pluck from an even distribution like in the accepted answer and it's as random as rand() is which is reasonably so. – Kit Sunde Oct 09 '15 at 14:57
  • @KitSunde - it makes literally no difference in the end. That's exactly the definition of overengineering and gold plating. – Davor Oct 09 '15 at 17:06
  • @Davor Well if you want to not overengineer you may as well do `function generateRandomString(){return "asdf"; /* Decided by fair dice roll */ }`. ;) The definition of over engineering isn't making a function 7 lines long so it does what it advertised it does and doesn't just surprisingly fail when being asked for more than 40 characters. ;) There's also something called "the principle of least surprise". But shrug, good talk, I think I'm happy that you're happy, I have no need to discuss this further. – Kit Sunde Oct 09 '15 at 17:50
  • @KitSunde - except that one wouldn't do the job, and this one does, perfectly for what is needed, in one simple line of code. – Davor Oct 11 '15 at 10:02
  • Very neat. Maybe rename the function "generateRandomHexString" to make it clear the string only contains hex characters? – Skyfish Jan 19 '22 at 20:14
19

$randstring in the function scope is not the same as the scope where you call it. You have to assign the return value to a variable.

$randstring = RandomString();
echo $randstring;

Or just directly echo the return value:

echo RandomString();

Also, in your function you have a little mistake. Within the for loop, you need to use .= so each character gets appended to the string. By using = you are overwriting it with each new character instead of appending.

$randstring .= $characters[rand(0, strlen($characters))];
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
16

First, you define the alphabet you want to use:

$alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$special  = '~!@#$%^&*(){}[],./?';
$alphabet = $alphanum . $special;

Then, use openssl_random_pseudo_bytes() to generate proper random data:

$len = 12; // length of password
$random = openssl_random_pseudo_bytes($len);

Finally, you use this random data to create the password. Because each character in $random can be chr(0) until chr(255), the code uses the remainder after division of its ordinal value with $alphabet_length to make sure only characters from the alphabet are picked (note that doing so biases the randomness):

$alphabet_length = strlen($alphabet);
$password = '';
for ($i = 0; $i < $len; ++$i) {
    $password .= $alphabet[ord($random[$i]) % $alphabet_length];
}

Alternatively, and generally better, is to use RandomLib and SecurityLib:

use SecurityLib\Strength;

$factory = new RandomLib\Factory;
$generator = $factory->getGenerator(new Strength(Strength::MEDIUM));

$password = $generator->generateString(12, $alphabet);
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
15

I've tested performance of most popular functions there, the time which is needed to generate 1'000'000 strings of 32 symbols on my box is:

2.5 $s = substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,32);
1.9 $s = base64_encode(openssl_random_pseudo_bytes(24));
1.68 $s = bin2hex(openssl_random_pseudo_bytes(16));
0.63 $s = base64_encode(random_bytes(24));
0.62 $s = bin2hex(random_bytes(16));
0.37 $s = substr(md5(rand()), 0, 32);
0.37 $s = substr(md5(mt_rand()), 0, 32);

Please note it is not important how long it really was but which is slower and which one is faster so you can select according to your requirements including cryptography-readiness etc.

substr() around MD5 was added for sake of accuracy if you need string which is shorter than 32 symbols.

For sake of answer: the string was not concatenated but overwritten and result of the function was not stored.

Putnik
  • 5,925
  • 7
  • 38
  • 58
14

Here's my simple one line solution to generate a use friendly random password, excluding the characters that lookalike such as "1" and "l", "O" and "0", etc... here it is 5 characters but you can easily change it of course:

$user_password = substr(str_shuffle('abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'),0,5);
rAthus
  • 810
  • 9
  • 17
  • 1
    This is perfect to create random ID strings to call later on jquery. IDK if its good practice but this helped me alot, without using a for like the accepted answer... – Rodrigo Zuluaga Nov 27 '19 at 21:52
  • This method is somewhat "less random" than you might first expect, since there is no chance any character will be used more than once. – Deji Jul 26 '20 at 02:26
  • You're right @Deji, a five characters length string will "only" have 379 million possible combinations instead of 459 million. – rAthus Jul 28 '20 at 15:01
  • It's actually just under 312 million permutations that your 5-char sub-strings can generate. I'm not sure how to calculate the latter to be honest. – Deji Jul 29 '20 at 17:43
  • @Deji how did you get to 312M? The songs pics the first from 54 characters, then from the remaining ones, etc, five times, that's 54*53*52*51*50 = 379.501.200 possible combinations. – rAthus Jul 30 '20 at 18:29
  • @rAthus Oh, because I assumed you were just using both upper and lower case alphabetical characters (thus 52) more like what the OP was doing... but for some reason you're using a subset of alpha-numerics? Now I question the usage of such a random string generation at all, as generating something that's supposed to be secure in a way that's human readable are at odds, and using `str_shuffle` is probably not cryptographically secure. – Deji Jul 31 '20 at 22:05
  • @Deji OP is using numbers as well making his string 62 chars so that would be even MORE possible outcomes, why I chose to reduce as explained in my post, it is made to be user friendly by removing look alike characters so that a humain has no trouble reading it whatever font is used, and using only a one-line light function, this can be very useful when generating a random password for a user for example, or a strong discount code, or magic key to access simething, etc... – rAthus Aug 06 '20 at 14:39
13
function gen_uid($l=5){
   return substr(str_shuffle("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 10, $l);
}
echo gen_uid();

Default Value[5]: WvPJz

echo gen_uid(30);

Value[30]: cAiGgtf1lDpFWoVwjykNKXxv6SC4Q2

CodAIK
  • 715
  • 7
  • 7
12

One very quick way is to do something like:

substr(md5(rand()),0,10);

This will generate a random string with the length of 10 chars. Of course, some might say it's a bit more heavy on the computation side, but nowadays processors are optimized to run md5 or sha256 algorithm very quickly. And of course, if the rand() function returns the same value, the result will be the same, having a 1 / 32767 chance of being the same. If security's the issue, then just change rand() to mt_rand()

BassMHL
  • 8,523
  • 9
  • 50
  • 67
Akatosh
  • 448
  • 9
  • 17
12

Short Methods..

Here are some shortest method to generate the random string

<?php
echo $my_rand_strng = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), -15); 

echo substr(md5(rand()), 0, 7);

echo str_shuffle(MD5(microtime()));
?>
Punit Gajjar
  • 4,937
  • 7
  • 35
  • 70
9

Helper function from Laravel 5 framework

/**
 * Generate a "random" alpha-numeric string.
 *
 * Should not be considered sufficient for cryptography, etc.
 *
 * @param  int  $length
 * @return string
 */
function str_random($length = 16)
{
    $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
}
artnikpro
  • 5,487
  • 4
  • 38
  • 40
9

Since php7, there is the random_bytes functions. https://www.php.net/manual/ru/function.random-bytes.php So you can generate a random string like that

<?php
$bytes = random_bytes(5);
var_dump(bin2hex($bytes));
?>
Vasil Kulakov
  • 190
  • 2
  • 4
8

from the yii2 framework

/**
 * Generates a random string of specified length.
 * The string generated matches [A-Za-z0-9_-]+ and is transparent to URL-encoding.
 *
 * @param int $length the length of the key in characters
 * @return string the generated random key
 */

function generateRandomString($length = 10) {
    $bytes = random_bytes($length);
    return substr(strtr(base64_encode($bytes), '+/', '-_'), 0, $length);
}
sxn
  • 157
  • 1
  • 7
SXN
  • 99
  • 1
  • 3
7
function rndStr($len = 64) {
     $randomData = file_get_contents('/dev/urandom', false, null, 0, $len) . uniqid(mt_rand(), true);
     $str = substr(str_replace(array('/','=','+'),'', base64_encode($randomData)),0,$len);
    return $str;
}
7

This one was taken from adminer sources:

/** Get a random string
* @return string 32 hexadecimal characters
*/
function rand_string() {
    return md5(uniqid(mt_rand(), true));
}

Adminer, database management tool written in PHP.

userlond
  • 3,632
  • 2
  • 36
  • 53
5

Another one-liner, which generates a random string of 10 characters with letters and numbers. It will create an array with range (adjust the second parameter to set the size), loops over this array and assigns a random ASCII character (range 0-9 or a-z), then implodes the array to get a string.

$str = implode('', array_map(function () { return chr(rand(0, 1) ? rand(48, 57) : rand(97, 122)); }, range(0, 9)));

Note: this only works in PHP 5.3 and later

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kasimir
  • 1,506
  • 1
  • 20
  • 26
  • finally a truly random solution not some bloated hash of a 32 bit random integer or a shuffled string... – The Surrican Sep 13 '14 at 14:15
  • theres just one issue: numbers are as likely to occur as characters, which is not as random as i would love to have it. anyaway +1 for the best solution on this page. tweak that and its perfect. – The Surrican Sep 14 '14 at 01:19
  • tweak... like this? `rand(0, 57-48+122-97)<57-48?...:...` ? :) – vp_arth Jan 12 '15 at 12:23
5

One liner.

It is fast for huge strings with some uniqueness.

function random_string($length){
    return substr(str_repeat(md5(rand()), ceil($length/32)), 0, $length);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jacob Smith
  • 89
  • 1
  • 5
5
function randomString($length = 5) {
    return substr(str_shuffle(implode(array_merge(range('A','Z'), range('a','z'), range(0,9)))), 0, $length);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Anjith K P
  • 2,158
  • 27
  • 35
5
/**
 * @param int $length
 * @param string $abc
 * @return string
 */
function generateRandomString($length = 10, $abc = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
{
    return substr(str_shuffle($abc), 0, $length);
}

Source from http://www.xeweb.net/2011/02/11/generate-a-random-string-a-z-0-9-in-php/

mike_t
  • 2,484
  • 2
  • 21
  • 39
sxn
  • 157
  • 1
  • 7
4

The edited version of the function works fine, but there is just one issue I found: You used the wrong character to enclose $characters, so the ’ character is sometimes part of the random string that is generated.

To fix this, change:

$characters = ’0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;

to:

$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

This way only the enclosed characters are used, and the ’ character will never be a part of the random string that is generated.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bmcswee
  • 107
  • 2
  • 6
4

Here is how I am doing it to get a true unique random key:

$Length = 10;
$RandomString = substr(str_shuffle(md5(time())), 0, $Length);
echo $RandomString;

You can use time() since it is a Unix timestamp and is always unique compared to other random mentioned above. You can then generate the md5sum of that and take the desired length you need from the generated MD5 string. In this case I am using 10 characters, and I could use a longer string if I would want to make it more unique.

I hope this helps.

James McCracken
  • 15,488
  • 5
  • 54
  • 62
sherpa
  • 73
  • 1
  • 2
  • 2
    Of course, `time()` is far from unique: it'll return the same value again and again until current second ends. What really provides some randomness here is `str_shuffle()`—the rest of the code only reduces the sample to pick chars from. – Álvaro González Apr 21 '14 at 16:03
  • 1
    so what you are basically doing is shuffling around a 32 bit integer. not a lot of entropy here... – The Surrican Sep 13 '14 at 14:15
  • 2
    An attacker can guess the value returned by `time()` (it's only a timestamp), it's a weak source of randomness. – A.L Nov 28 '14 at 14:04
  • Please note, he also uses a str_shuffle. Even if an attacker guess the time, he cannot guess the result of the shuffle function. I think it is secure enough. – Serdar D. Jul 27 '22 at 20:02
4
function generateRandomString($length = 10, $hasNumber = true, $hasLowercase = true, $hasUppercase = true): string
{
    $string = '';
    if ($hasNumber)
        $string .= '0123456789';
    if ($hasLowercase)
        $string .= 'abcdefghijklmnopqrstuvwxyz';
    if ($hasUppercase)
        $string .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    return substr(str_shuffle(str_repeat($x = $string, ceil($length / strlen($x)))), 1, $length);
}

and use:

echo generateRandomString(32);
MRMP
  • 303
  • 2
  • 5
3

I liked the last comment which used openssl_random_pseudo_bytes, but it wasn't a solution for me as I still had to remove the characters I didn't want, and I wasn't able to get a set length string. Here is my solution...

function rndStr($len = 20) {
    $rnd='';
    for($i=0;$i<$len;$i++) {
        do {
            $byte = openssl_random_pseudo_bytes(1);
            $asc = chr(base_convert(substr(bin2hex($byte),0,2),16,10));
        } while(!ctype_alnum($asc));
        $rnd .= $asc;
    }
    return $rnd;
}
RKaneKnight
  • 181
  • 2
  • 4
3

You can try this:

<?php
    function random($len){

        $char = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

        // ----------------------------------------------
        // Number of possible combinations
        // ----------------------------------------------
        $pos = strlen($char);
        $pos = pow($pos, $len);
        echo $pos.'<br>';
        // ----------------------------------------------

        $total = strlen($char)-1;
        $text = "";

        for ($i=0; $i<$len; $i++){
            $text = $text.$char[rand(0, $total)];
        }
        return $text;
    }

    $string = random(15);
    echo $string;
?>

You can also use md5 on time but be careful.

You need to use microtime() and not time() function, because if multiple threads run within the same second, you need to get different string for all of them.

<?php

    $string = md5(microtime());
    echo $string;
?>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aominé
  • 472
  • 3
  • 11
3
//generateRandomString http://stackoverflow.com/questions/4356289/php-random-string-generator
function randomString($length = 32, $string= "0123456789abcdefghijklmnopqrstuvwxyz" ) {
    //$string can be:
    //0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
    //0123456789abcdefghijklmnopqrstuvwxyz
    return substr(str_shuffle( $string), 0, $length);
}
Hoàng Vũ Tgtt
  • 1,863
  • 24
  • 8
2

Another way to generate a random string in PHP is:

function RandomString($length) {
    $original_string = array_merge(range(0,9), range('a','z'), range('A', 'Z'));
    $original_string = implode("", $original_string);
    return substr(str_shuffle($original_string), 0, $length);
}
echo RandomString(6);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Akhilraj N S
  • 9,049
  • 5
  • 36
  • 42
2

There is simple code:

echo implode("",array_map(create_function('$s','return substr($s,mt_rand(0,strlen($s)),1);'),array_fill(0,16,"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")));

There is a simple guide:

  • To change the length of string, please change the 16 to another value, only.
  • To select from different characters, please change the character string.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
16ctt1x
  • 321
  • 6
  • 21
2

Parametrised one-liner using only PHP native functions, working since PHP 5.1.0

str_shuffle(implode('', (array_intersect_key(($map =  array_map('chr', array_merge(array_map('mt_rand', array_fill(0, $length = 25, 48), array_fill(0,$length,57)),array_map('mt_rand', array_fill(0, $length, 65), array_fill(0,$length,90)),array_map('mt_rand', array_fill(0, $length, 97), array_fill(0,$length,122))))), array_flip($keys = array_rand($map, $length))))))
user10099
  • 1,345
  • 2
  • 17
  • 23
2

Here's a one-liner. You'll get at least one lower-case, one upper-case, one number, and one symbol. Uses random_int which is supposed to cyrptographically secure. I do not claim this to be secure, though. I am not a security expert.

To copy+Paste: (just change $len to your desired length.)

$len=26;for ($chars = array('0123456789','abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ','!@#$%^&*()_+-='),$randomString="",$i=0;$i<$len;$i++)$randomString .= substr($chars[$i%4], random_int(0,strlen($chars[$i%4])), 1);
echo $randomString;

And a little more broken down:

for (
        $chars = array('0123456789','abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ','!@#$%^&*()_+-='),
        $randomString="",
        $i=0;
        $i<12;$i++)
        $randomString .= 
            substr($chars[$i%4], 
                random_int(0, strlen($chars[$i%4])), 1);

I use $chars[$i%4] in the loop to choose which set of characters to get a random from. It guarantees multiple characters from each set of chars in the array.

It could definitely be improved (randomizing how many of each char set there is), but it's good enough for my purposes.

Reed
  • 14,703
  • 8
  • 66
  • 110
2

Here is another solution.

function genRandomString($length = 10)
{
    if($length < 1)
        $length = 1;
    return substr(preg_replace("/[^A-Za-z0-9]/", '', base64_encode(openssl_random_pseudo_bytes($length * 2))), 0, $length);
}

PS. I am using PHP 7.2 on Ubuntu.

Umair Khan
  • 1,684
  • 18
  • 34
1
function randomName($length = 8) {
  $values = array_merge(range(65, 90), range(97, 122), range(48, 57));
  $max = count($values) - 1;
  $str = chr(mt_rand(97, 122));
  for ($i = 1; $i < $length; $i++) {
    $str .= chr($values[mt_rand(0, $max)]);
  }
  return $str;
}
mrded
  • 4,674
  • 2
  • 34
  • 36
1
function getRandomString($length) {
  $salt = array_merge(range('a', 'z'), range(0, 9));
  $maxIndex = count($salt) - 1;

  $result = '';
  for ($i = 0; $i < $length; $i++) {
    $index = mt_rand(0, $maxIndex);
    $result .= $salt[$index];
  }
  return $result
}
Ryan Williams
  • 1,465
  • 15
  • 19
1

Source: PHP Function that Generates Random Characters

This PHP function worked for me:

function cvf_ps_generate_random_code($length=10) {

   $string = '';
   // You can define your own characters here.
   $characters = "23456789ABCDEFHJKLMNPRTVWXYZabcdefghijklmnopqrstuvwxyz";

   for ($p = 0; $p < $length; $p++) {
       $string .= $characters[mt_rand(0, strlen($characters)-1)];
   }

   return $string;

}

Usage:

echo cvf_ps_generate_random_code(5);
Carl
  • 805
  • 12
  • 24
1

The following function generates pseudo string of any length.

/**
 * Returns random string of a given length.
 */
function get_random_string($length) {
  $pull = [];
  while (count($pull) < $length) {
    $pull = array_merge($pull, range(0, 9), range('a', 'z'), range('A', 'Z'));
  }
  shuffle($pull);
  return substr(implode($pull), 0, $length);
}
ya.teck
  • 2,060
  • 28
  • 34
1

You are doing it totally wrong, because you're depending on numbers, not characters and I am not sure if you want the random output to be just numbers, if so why the need to get all the alphabetic letters and all numbers and extract their length? Why not you just use rand(0, 62)?, even though you've forgot to initialize your variable $randstring before you declare the function.

Anyway, PHP offers you a very handy function for this purpose. It's str_shuffle(). Here is an example that suits your need.

<?php

function randomString() {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    return str_shuffle($characters);
}
echo randomString();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Wael Assaf
  • 1,233
  • 14
  • 24
1

Finally I have found a solution to get random and unique values.

My solution is:

substr(md5(time()), 0, 12)

time always return a timestamp, and it is always unique. You can use it with MD5 to make it better.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Junaid
  • 592
  • 1
  • 7
  • 24
  • 6
    Timestamp is **not** always unique and md5 does not make it better. If multiple threads run within the same second, this code will generate the same string for all of them. – Alex Howansky May 23 '17 at 15:07
1

A class with some of the functions from the discussions above.

$options['numeric'] = true;
$options['uppercase'] = true;
$options['lowercase'] = true;
$new = new RandomString($options);

class RandomString
{
    /**
     * @var array
     */
    private $default = ['numeric' => true, 'uppercase' => true, 'lowercase' => true];

    /**
     * @var array
     */
    private $options;

    /**
     * array
     */
    private $whitelist = ['numeric', 'uppercase', 'lowercase'];

    /**
     * RandomString constructor.
     *
     * @param array $options
     */
    public function __construct(array $options = [])
    {
        $this->options = $this->default;
        if(!empty($options))
        {
            $options = array_intersect_key($options, array_flip($this->whitelist));
            if(empty($options))
            {
                $this->options = $this->default;
            }else
            {
                $this->options = $options;
            }
        }
    }

    /**
     * @return string
     */
    private function returnCharacters(){

        $options = $this->options;

        $numbers = '0123456789';
        $uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $lowercase = "abcdefghijklmnopqrstuvwxyz";

        $characters = '';
        if(isset($options['numeric']) && $options['numeric'] === true){
            $characters .= $numbers;
        }

        if(isset($options['uppercase']) && $options['uppercase'] === true){
            $characters .= $uppercase;
        }

        if(isset($options['lowercase']) && $options['lowercase'] === true){
            $characters .= $lowercase;
        }
        return $characters;
    }

    /**
     * @param $length
     * @param $quantity
     * @return string
     */
    public function randomString($length, $quantity) {

        $string = '';
        $characters = $this->returnCharacters();

        for ($j = 0; $j < $quantity; $j++) {
            for($i = 0; $i < $length; $i++){
                $string .= $characters[mt_rand(0, strlen($characters) - 1)];
            }
            $string .= "\n";
        }
        return $string;
    }

    /**
     * @return array
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * @return mixed
     */
    public function getWhitelist()
    {
        return $this->whitelist;
    }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dixromos98
  • 756
  • 5
  • 18
1

In this method, you can choose the character length while creating.

<?php
    $random_string = "";
    $character_count = 12;
    for($i=1; $i <= $character_count; $i++)
    {
        $random_string .= chr(rand(97, 122));
    }
    echo $random_string;
?>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
1

Try this, it can generate up to length of master. but its simple and fit for small string.

$master="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$master_array = str_split($master);
shuffle($master_array);
print_r(implode("",array_slice($master_array,0,10)));
Madhan
  • 107
  • 12
0
<?php
    /**
     * Creates a random string
     *
     * @param (int) $length
     *   Length in characters
     * @param (array) $ranges
     *   (optional) Array of ranges to be used
     *
     * @return
     * Random string
    */
    function random_string($length, $ranges = array('0-9', 'a-z', 'A-Z')) {
        foreach ($ranges as $r) $s .= implode(range(array_shift($r = explode('-', $r)), $r[1]));
        while (strlen($s) < $length) $s .= $s;
        return substr(str_shuffle($s), 0, $length);
    }

    // Examples:
    $l = 100;
    echo '<b>Default:</b> ' . random_string($l) . '<br />';
    echo '<b>Lower Case only:</b> ' . random_string($l, array('a-z')) . '<br />';
    echo '<b>HEX only:</b> ' . random_string($l, array('0-9', 'A-F')) . '<br />';
    echo '<b>BIN only:</b> ' . random_string($l, array('0-1')) . '<br />';

/* End of file */
Geo
  • 12,666
  • 4
  • 40
  • 55
  • if you want to be using proper PHP, replace the first line of the function with `foreach ($ranges as $r) $s .= implode('', range(array_shift($r = explode('-', $r)), $r[1]));` – Geo Nov 14 '12 at 18:59
0
function randomString() {
       return md5(rand(100, 200));
}
  • 3
    This is only partly random, since you are limiting it to 100 unique combinations. Additionally, md5 will always return a string with 32 characters length. Good for general usage, but not if you need a huge amount of truly unique strings. See my answer for an example with better randomness using the current time, md5() and `base64_decode()`. – Dzhuneyt Sep 04 '13 at 10:43
0

If you are using this random string in a place where a user might see it or use it (eg as a password generator, you might want to limit the set of characters used to exclude vowels. That way you will not accidentally generate bad words and offend someone. Don't laugh it happens.

  • 1
    Also, I would add that you shouldn't include visually similar characters, e.g. `1=>l (lowercase L), 0 (digit)=>O (letter)`. These can be confusing to the user since they look similar at first glance, so only stick to the distinct ones. – Dzhuneyt Sep 04 '13 at 10:45
0

I say take the best of several answers and put them together - str_suffle and range are new to me:

echo generateRandomString(25); // Example of calling it

function generateRandomString($length = 10) {
    return substr(str_shuffle(implode(array_merge(range(0,9), range('A', 'Z'), range('a', 'z')))), 0, $length);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mark ee
  • 17
  • 2
  • 2
    This is limited to 62 characters, due to the fact that you are simply concatenating the 3 ranges (0-9, a-z, A-Z) in a 62 long string and then shuffling the characters and getting the first N characters (so N can be at most 62). The function can be reworked to make a recursive call to itself when a length of more than 62 characters is requested, but just wanted to point out the current limit for anyone reading this. – Dzhuneyt Sep 04 '13 at 10:51
  • a lot of effort for little entropy here... you can do better than that. – The Surrican Sep 13 '14 at 14:22
0
$t = array_merge(range('0', '9'), range('a', 'z'), range('A', 'Z'));
echo join('', array_map(function() use($t) { return $t[array_rand($t)]; }, range(1, 15)));

or one-liner

echo join('', array_map(function() { return substr('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', rand(0, 61), 1); }, range(1, 15)));
Cheery
  • 16,063
  • 42
  • 57
0

I always liked to use base64 for generating random passwords or other random (printable) character strings. The usage of base64 ensures a large number of printable characters is available.

On the shell, I usually do something like this:

base64 < /dev/urandom |head -c10

Something similar can be done in PHP as well. However reading directly from /dev/urandom might be forbidden by open_basedir restrictions. So this is what I've arrived at:

base64_encode(
    join(
        '',
        array_map(
            function($x){ return chr(mt_rand(1,255));},
            range(1,15)
        )
    )
);

To get a truly random string, we need random input as well. This is what the join/array_map does. Using something like uniqid is not enough, because it will always have a similar prefix, as it's basically a glorified timestamp.

If you have the openssl extension installed, you can of course use openssl_random_pseudo_bytes() instead, which would be even better.

Dave Vogt
  • 18,600
  • 7
  • 42
  • 54
  • Yes, use `openssl_random_pseudo_bytes()` if you can! Don't settle for `mt_rand()`, see [this answer](http://stackoverflow.com/a/31107425/2224584) for an implementation that uses a CSPRNG. – Scott Arciszewski Jun 29 '15 at 03:44
0

Please, try this my function to generate a custom random alphanumeric string:

<?php
  function random_alphanumeric($length) {
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
    $my_string = '';
    for ($i = 0; $i < $length; $i++) {
      $pos = random_int(0, strlen($chars) -1);
      $my_string .= substr($chars, $pos, 1);
    }
    return $my_string;
  }
?>

You can adjust the result by passing the length of the string to the function like below:

  $test_with_50_items = random_alphanumeric(50); // 50 characters
  echo $test_with_50_items;

Example (test_with_50_items): Y1FypdjVbFCFK6Gh9FDJpe6dciwJEfV6MQGpJqAfuijaYSZ86

If you need more than 50 chars or less simply call the function how you like:

  $test_with_27_items = random_alphanumeric(27); // 27 characters
  echo $test_with_27_items;

If you need two or more unique strings you can do by loop using while so you are sure to get two unique strings... you can do the same with more strings, the only limit is your fantasy...

  $string_1 = random_alphanumeric(50);
  $string_2 = random_alphanumeric(50);
  while ($string_1 == $string_2) {
    $string_1 = random_alphanumeric(50);
    $string_2 = random_alphanumeric(50);
    if ($string_1 != $string_2) {
       break;
    }
  }
  echo $string_1;
  echo "<br>\n";
  echo $string_2;

$string_1: KkvUwia8rbDEV2aChWqm3AgeUZqyrRbUx2AxVhx5s4TSJ2VwA4

$string_2: XraO85YfxBBCInafvwipSOJwLmk6JMWiuWOxYQDnXohcn2D8K6

According to PHP 8.3 random_int() is "secure by default"

Alessandro
  • 900
  • 12
  • 23
0
function strgen($len) {
    $buf = '';
    for ($i = 0; $i < $len; $i++) {
        $j = mt_rand(0, 61);
        if ($j >= 36) {
            $j += 13;
        } else if ($j >= 10) {
            $j += 7;
        }
        $buf .= chr(48 + $j);
    }
    return $buf;
}

Simple and elegant.

ch1p_
  • 1,193
  • 2
  • 8
  • 15
0

IF YOUR ARE USING PHP 7 +

public function generateRandom(){

$string = bin2hex(openssl_random_pseudo_bytes(10)); // 20 chars

// OR

$string = base64_encode(random_bytes(10)); // ~14 characters, includes /=+

// or

$string = substr(str_replace(['+', '/', '='], '', base64_encode(random_bytes(32))), 0, 32); // 32 characters, without /=+

// or

$string = bin2hex(random_bytes(10)); // 20 characters, only 0-9a-f

}
Boken
  • 4,825
  • 10
  • 32
  • 42
Vivek Pawar
  • 339
  • 3
  • 5
0

This code will help:

This function will return random string with length between $maxLength and $minLength.

NOTE: Function random_bytes works since PHP 7.

If you need specific length, so $maxLength and $minLength must be same.

function getRandomString($maxLength = 20, $minLength = 10)
{
    $minLength = $maxLength < $minLength ? $maxLength : $minLength;
    $halfMin = ceil($minLength / 2);
    $halfMax = ceil($maxLength / 2);
    $bytes = random_bytes(rand($halfMin, $halfMax));
    $randomString = bin2hex($bytes);
    $randomString = strlen($randomString) > $maxLength ? substr($randomString, 0, -1) : $randomString;
    return $randomString;
}
0

A full solution (class plus test), partly based on some suggestions above...

class TokenFactory
{
    private const LENGTH = 12;
    private const ALLOWED = '123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ~!@#$%^&*{}';
    private const MIN_NUMBER_OF_DIGITS = 1;
    private const MIN_NUMBER_OF_CAPS = 1;
    private const MIN_NUMBER_OF_SPECIALS = 1;
    private const MIN_NUMBER_OF_LETTERS = 1;

    /**
     * @return string
     * @throws \Exception
     */
    public function make(): string
    {
        $pass = $this->generateToken();

        if ($this->isTokenValid($pass)) {
            return $pass;
        } else {
            return $this->make();
        }
    }

    /**
     * @return string
     * @throws \Exception
     */
    private function generateToken(): string
    {
        $allowedCharacters = self::ALLOWED;
        $token              = '';
        $max               = mb_strlen($allowedCharacters, '8bit') - 1;
        for ($i = 0; $i < self::LENGTH; ++$i) {
            $token .= $allowedCharacters[random_int(0, $max)];
        }
        return $token;
    }

    /**
     * @param $token
     * @return bool
     */
    private function isTokenValid($token): bool
    {
        $numberOfDigits   = preg_match_all("/[0-9]/", $token);
        $numberOfCaps     = preg_match_all("/[A-Z]/", $token);
        $numberOfSpecials = preg_match_all("/[~!@#\$%^&*{}]/", $token);
        $numberOfLetters  = preg_match_all("/[a-z]/", $token);

        return
            $numberOfDigits > self::MIN_NUMBER_OF_DIGITS
            && $numberOfCaps > self::MIN_NUMBER_OF_CAPS
            && $numberOfSpecials > self::MIN_NUMBER_OF_SPECIALS
            && $numberOfLetters > self::MIN_NUMBER_OF_LETTERS
            ;
    }
}

class TokenFactoryTest
{
    public function test_correct_syntax()
    {
        /**
         * Arrange
         */
        $length = 12;
        $numberOfChecks = 1000;

        /**
         * Act & Assert
         */
        $class = new TokenFactory();

        $i = 0;
        while ($i < $numberOfChecks) {
            $generatedToken = $class->make();

            $numberOfDigits = preg_match_all( "/[0-9]/", $generatedToken );
            $numberOfCaps = preg_match_all( "/[A-Z]/", $generatedToken );
            $numberOfSpecials   = preg_match_all("/[~!@#\$%^&*{}]/", $generatedToken);
            $numberOfLetters   = preg_match_all("/[a-z]/", $generatedToken);

            Assert::assertEquals($length, strlen($generatedToken));
            Assert::assertTrue($numberOfDigits >= 1, 'Digit error: ' . $generatedToken);
            Assert::assertTrue($numberOfCaps >= 1, 'Caps error: ' . $generatedToken);
            Assert::assertTrue($numberOfSpecials >= 1, 'Specials error: ' . $generatedToken);
            Assert::assertTrue($numberOfLetters >= 1, 'Letters error: ' . $generatedToken);

            $i++;
        }
    }
}

BTW make sure to catch that exception somewhere where it suits your needs!

redcenter
  • 826
  • 4
  • 10
0

If you are morbidly scared of typing out letters of the alphabet, don't care about string security, and are only interested in alphabets, here's a neat solution

$alphabets = range ("a", "z");
shuffle ($alphabets);
$randomString = substr(implode ("", $alphabets), 3, 17); // adjust according to desired length 
I Want Answers
  • 371
  • 3
  • 15
0

Laravel solution: If you are using Laravel Framework, you can use its StringHelper like this.

use Illuminate\Support\Str;

Str::random($strlentgh = 16)

0

recursive solution:

public static function _random(string $set , int $length): string
{
    $setLength = strlen($set);
    $randomKey = random_int(0, $setLength - 1);

    $firstPiece = substr($set, 0, $randomKey);
    $secondPiece = substr($set, $randomKey, $setLength - $randomKey);

    $removedCharacter = $firstPiece[strlen($firstPiece) - 1] ?? null;
    if(null === $removedCharacter || $length === 0) {
        return '';
    }
    $firstPieceWithoutTheLastChar = substr($firstPiece, 0, -1);

    return $removedCharacter . self::_random($firstPieceWithoutTheLastChar . $secondPiece, $length - 1);
}

nice performance , https://3v4l.org/aXaJ6/perf

Pascual Muñoz
  • 189
  • 1
  • 5
0

I wanted pseudorandom strings of specific characters and a preset length. I wanted the highest quality pseudorandomness practically possible for the current version of PHP, at this time it could be v5, v6, v7, or v8, and it could be using default configuration or special. To tame this chaos, I sampled several of the other answers here and included function availability conditionals.

Usage. To use it globally assign $VALID_ID_CHARS with whatever characters you want and then call it:

$VALID_ID_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
$myNewRandomId = makeId(6);
function makeId($desiredLen)
{
    global $VALID_ID_CHARS;
    if ($desiredLen < 1) {
        throw new \RangeException("Length must be a positive integer");
    }
    $vLen = 0;
    if (function_exists('mb_strlen')) {
        $vLen = mb_strlen($VALID_ID_CHARS, '8bit') - 1;
    } else {
        $vLen = strlen($VALID_ID_CHARS) - 1;
    }
    if (function_exists('random_int')) {
        $pieces = [];
        for ($i = 0; $i < $desiredLen; ++$i) {
            $pieces[] = $VALID_ID_CHARS[random_int(0, $vLen)];
        }
        return implode('', $pieces);
    }
    if (function_exists('openssl_random_pseudo_bytes')) {
        $random = openssl_random_pseudo_bytes($desiredLen);
        $id = '';
        for ($i = 0; $i < $desiredLen; ++$i) {
            $id .= $VALID_ID_CHARS[ord($random[$i]) % $vLen];
        }
        return $id;
    }
    http_response_code(500);
    die('random id generation failed. either random_int or openssl_random_pseudo_bytes is needed');
}
fartwhif
  • 321
  • 3
  • 12
0

Starting from php8.3 you can do this:

$rng = new Random\Randomizer();
$crockfordAlphabet = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
$rng->getBytesFromString($crockfordAlphabet, 10); // "5YH837JSJT"
sensorario
  • 20,262
  • 30
  • 97
  • 159
-1

If you need large number of random strings with no duplicates, here's a recursive code with small modification:

function generateRandomString($length = 10)
{
    global $generatedStrings;
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, strlen($characters) - 1)];
    }
    if (isset($generatedStrings[$randomString])) {
        $randomString = generateRandomString($length);
    }
    $generatedStrings[$randomString] = $randomString;
    return $randomString;
}

$generatedStrings = array();

foreach(range(1, 100000) as $num) {
    echo "\n".$num."\t : ".generateRandomString();
}
dhavald
  • 524
  • 4
  • 12
-1

Try this:

function generate_name ($length = LENGTH_IMG_PATH) {
    $image_name = "";
    $possible = "0123456789abcdefghijklmnopqrstuvwxyz";

    $i = 0;

    while ($i < $length) {

        $char = substr($possible, mt_rand(0, strlen($possible)-1), 1);

        if (!strstr($image_name, $char)) {
            $image_name .= $char;
            $i++;
        }
    }
    return $image_name;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ayman Hussein
  • 3,817
  • 7
  • 28
  • 48
-1

To get it in a single line, try this:

$str = substr(str_shuffle(str_repeat("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 5)), 0, $length);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ruwantha
  • 2,603
  • 5
  • 30
  • 44
  • After 65,536 random strings generated this way, you can expect to have generated the same string twice, even with an arbitrarily large `$length`. Weak PRNGs produce collisions (and are predictable!) – Scott Arciszewski Dec 08 '15 at 06:31
  • str_shuffle — Randomly shuffles a string according to the PHP docs. So how could you tell that it is not going to be same string twice. – Ruwantha Dec 08 '15 at 11:03
-1

Previous answers generate passwords that are insecure or difficult to type.

This one is secure and provides a password that users are more likely to actually use, instead of being discarded for something weak.

// NOTE: On PHP 5.x you will need to install https://github.com/paragonie/random_compat

/**
 * Generate a password that can easily be typed by users.
 *
 * By default, this will sacrifice strength by skipping characters that can cause
 * confusion. Set $allowAmbiguous to allow these characters.
 */
static public function generatePassword($length=12, $mixedCase=true, $numericCount=2, $symbolCount=1, $allowAmbiguous=false, $allowRepeatingCharacters=false)
{
  // sanity check to prevent endless loop
  if ($numericCount + $symbolCount > $length) {
    throw new \Exception('generatePassword(): $numericCount + $symbolCount are too high');
  }

  // generate a basic password with just alphabetic characters
  $chars  = 'qwertyupasdfghjkzxcvbnm';
  if ($mixedCase) {
    $chars .= 'QWERTYUPASDFGHJKZXCVBNML';
  }
  if ($allowAmbiguous) {
    $chars .= 'iol';
    if ($mixedCase) {
      $chars .= 'IO';
    }
  }

  $password = '';
  foreach (range(1, $length) as $index) {
    $char = $chars[random_int(0, strlen($chars) - 1)];

    if (!$allowRepeatingCharacters) {
      while ($char == substr($password, -1)) {
        $char = $chars[random_int(0, strlen($chars) - 1)];
      }
    }

    $password .= $char;
  }


  // add numeric characters
  $takenSubstitutionIndexes = [];

  if ($numericCount > 0) {
    $chars = '23456789';
    if ($allowAmbiguous) {
      $chars .= '10';
    }

    foreach (range(1, $numericCount) as $_) {
      $index = random_int(0, strlen($password) - 1);
      while (in_array($index, $takenSubstitutionIndexes)) {
        $index = random_int(0, strlen($password) - 1);
      }

      $char = $chars[random_int(0, strlen($chars) - 1)];
      if (!$allowRepeatingCharacters) {
        while (substr($password, $index - 1, 1) == $char || substr($password, $index + 1, 1) == $char) {
          $char = $chars[random_int(0, strlen($chars) - 1)];
        }
      }

      $password[$index] = $char;
      $takenSubstitutionIndexes[] = $index;
    }
  }

  // add symbols
  $chars = '!@#$%&*=+?';
  if ($allowAmbiguous) {
    $chars .= '^~-_()[{]};:|\\/,.\'"`<>';
  }

  if ($symbolCount > 0) {
    foreach (range(1, $symbolCount) as $_) {
      $index = random_int(0, strlen($password) - 1);
      while (in_array($index, $takenSubstitutionIndexes)) {
        $index = random_int(0, strlen($password) - 1);
      }

      $char = $chars[random_int(0, strlen($chars) - 1)];
      if (!$allowRepeatingCharacters) {
        while (substr($password, $index - 1, 1) == $char || substr($password, $index + 1, 1) == $char) {
          $char = $chars[random_int(0, strlen($chars) - 1)];
        }
      }

      $password[$index] = $char;
      $takenSubstitutionIndexes[] = $index;
    }
  }

  return $password;
}
Abhi Beckert
  • 32,787
  • 12
  • 83
  • 110
-1

The one line solution will be

str_shuffle(base64_encode(date('mdyhis').date('mdyhis')));
mujaffars
  • 1,395
  • 2
  • 15
  • 35
-1

There are 3 things wrong with your code:

  1. $randstring is not assigned to anything (only inside the function which is out of scope).
  2. RandomString only returns the last random charactor. Replace = with .=.
  3. Rand does not generate cryptographically secure pseudo-random numbers. Use random_int instead.

See below:

<?php
    function RandomString()
    {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $randstring = '';
        for ($i = 0; $i < 10; $i++) {
            $randstring .= $characters[random_int(0, strlen($characters))];
        }
        return $randstring;
    }
    $randstring = RandomString();
    echo $randstring;
Dan Bray
  • 7,242
  • 3
  • 52
  • 70
-2
$pass = "";
for ($i=0;$i<12;++$i)
  $pass.= ($r=mt_rand(0,35))<26?chr(ord('a')+$r):chr(ord('0')+$r-26);
AbiusX
  • 2,379
  • 20
  • 26