我试图在PHP中创建一个随机字符串,我得到绝对没有输出:

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

    RandomString();
    echo $randstring;

我做错了什么?


当前回答

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

或一行程序

echo join('', array_map(function() { return substr('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', rand(0, 61), 1); }, range(1, 15)));

其他回答

注意:str_shuffle()内部使用rand(),不适合用于加密目的(例如生成随机密码)。你需要一个安全的随机数生成器。它也不允许字符重复。

还有一种方法。

UPDATED(现在这会生成任意长度的字符串):

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

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

就是这样。:)

这将创建一个20个字符的十六进制字符串:

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

在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

实现这个函数的更好方法是:

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在PHP 7中更加随机。rand函数是mt_rand的别名。

这是我简单的一行解决方案,以生成一个使用友好的随机密码,排除字符看起来像“1”和“l”,“O”和“0”,等等…这里是5个字符,但你可以很容易地改变它:

$user_password = substr(str_shuffle('abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'),0,5);

一个完整的解决方案(课程加测试),部分基于上面的一些建议…

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

顺便说一句,请确保在适合您需要的地方捕获该异常!