我试图在PHP中创建一个随机字符串,我得到绝对没有输出:
<?php
function RandomString()
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randstring = '';
for ($i = 0; $i < 10; $i++) {
$randstring = $characters[rand(0, strlen($characters))];
}
return $randstring;
}
RandomString();
echo $randstring;
我做错了什么?
下面是一个简单的单行程序,它生成一个真正的随机字符串,而不需要任何脚本级循环或使用OpenSSL库。
echo substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', mt_rand(1,10))), 1, 10);
把它分解,这样参数就清楚了
// 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);
此方法的工作原理是随机重复字符列表,然后打乱组合的字符串,并返回指定的字符数。
您可以进一步随机化它,通过随机化返回字符串的长度,将$chrRandomLength替换为mt_rand(8,15)(用于8到15个字符之间的随机字符串)。
具体回答这个问题,有两个问题:
当你回显$randstring时,它不在作用域内。
字符在循环中没有连接在一起。
以下是更正后的代码片段:
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;
}
用下面的调用输出随机字符串:
// Echo the random string.
// Optionally, you can give it a desired string length.
echo generateRandomString();
请注意,这个答案的以前版本使用rand()而不是random_int(),因此生成可预测的随机字符串。因此,根据这个答案的建议,它被更改为更安全。
一个完整的解决方案(课程加测试),部分基于上面的一些建议…
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++;
}
}
}
顺便说一句,请确保在适合您需要的地方捕获该异常!
另一个一行程序,生成一个包含字母和数字的10个字符的随机字符串。它将创建一个具有范围的数组(调整第二个参数以设置大小),循环遍历该数组并分配一个随机ASCII字符(范围0-9或a-z),然后内爆该数组以获得一个字符串。
$str = implode('', array_map(function () { return chr(rand(0, 1) ? rand(48, 57) : rand(97, 122)); }, range(0, 9)));
注意:这只适用于PHP 5.3及更高版本