Генератор случайного кода на PHP

Генерация случайной строки в программировании — популярная тема. Это связано с тем, что таким образом ресурсы можно защитить или сделать уникальными. В большинстве технологий есть готовые решения, позволяющие, например, генерировать UUID или другие типы идентификаторов. Очень полезная вещь. Однако иногда возникает потребность в чем-то более конкретном. Я имею в виду более короткие случайные строки . Они могут действовать как, например, коды доступа, пин-коды или просто пароли.
<?php
class CodeGenerator
{
    public const DEFAULT_LENGTH = 10;
    public const DEFAULT_CHARACTERS = 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPrRsStTuUvVwWxXyYzZ0123456789';

    private CodeRepository $codeRepository;

    public function __construct(CodeRepository $codeRepository)
    {
        $this->codeRepository = $codeRepository;
    }

    public function generate(
        int $length = self::DEFAULT_LENGTH,
        string $allowedCharacters = self::DEFAULT_CHARACTERS
    ): string {
        if ($length < 3) {
            throw new \InvalidArgumentException('Code cannot be shorter than 3 chars');
        }

        $code = '';

        $allowedCharactersLength = mb_strlen($allowedCharacters);
        $codeLength = $length;
        while ($codeLength !== 0) {
            $randomIndex = mt_rand(0, $allowedCharactersLength - 1);
            $code .= $allowedCharacters[$randomIndex];

            $codeLength--;
        }

        if (!$this->codeRepository->isCodeUnique($code)) {
            return $this->generate($length, $allowedCharacters);
        }

        return $code;
    }
}
?>
<?php
interface CodeRepository
{
    public function isCodeUnique(string $code): bool;
}
?>
<?php
class CodeGeneratorTest extends TestCase
{
    public function testCannotGenerateNonUniqueCode(): void
    {
        $codeRepository = $this->prophesize(CodeRepository::class);
        $codeRepository
            ->isCodeUnique(Argument::type('string'))
            ->willReturn(false, false, true)
            ->shouldBeCalledTimes(3);
        $codeGenerator = new CodeGenerator($codeRepository->reveal());
        $codeGenerator->generate();
    }

    public function testCanGenerateCodeWithDefaultLength(): void
    {
        $codeRepository = $this->prophesize(CodeRepository::class);
        $codeRepository
            ->isCodeUnique(Argument::type('string'))
            ->willReturn(true);
        $codeGenerator = new CodeGenerator($codeRepository->reveal());
        $code = $codeGenerator->generate();

        $this->assertEquals(CodeGenerator::DEFAULT_LENGTH, strlen($code));
    }

    public function testCanGenerateCodeWithOtherLengthThanDefault(): void
    {
        $codeRepository = $this->prophesize(CodeRepository::class);
        $codeRepository
            ->isCodeUnique(Argument::type('string'))
            ->willReturn(true);
        $codeGenerator = new CodeGenerator($codeRepository->reveal());
        $code = $codeGenerator->generate(6);

        $this->assertSame(strlen($code), 6);
    }

    /** @dataProvider provideWrongCodeLength */
    public function testCannotGenerateCodeWithLengthLessThanThree(int $length): void
    {
        $codeRepository = $this->prophesize(CodeRepository::class);
        $codeGenerator = new CodeGenerator($codeRepository->reveal());

        $this->expectException(\InvalidArgumentException::class);

        $codeGenerator->generate($length);
    }

    public function testCannotGenerateCodeThatContainsOtherCharsThanSpecified()
    {
        $codeRepository = $this->prophesize(CodeRepository::class);
        $codeRepository
            ->isCodeUnique(Argument::type('string'))
            ->willReturn(true);
        $codeGenerator = new CodeGenerator($codeRepository->reveal());

        $allowedChars = 'aB0';
        $code = $codeGenerator->generate(20, $allowedChars);
        $regexChars = '/[^' . $allowedChars . ']/i';

        $this->assertEquals(0, preg_match($regexChars, $code));
    }

    public function provideWrongCodeLength(): array
    {
        return [
            'Length -1000' => [
                'length' => -1000
            ],
            'Length -1' => [
                'length' => -1
            ],
            'Length 0' => [
                'length' => 0
            ],
            'Length 1' => [
                'length' => 1
            ],
            'Length 2' => [
                'length' => 2
            ]
        ];
    }
}
?>

Вариант 2.

<?php

// Generate a Random String

function random_string( $length = 6 ) {

    $conso	= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    $vowels	= array( "a", "e", "i", "o", "u" );
    $string	= "";

    srand( (double)microtime()*1000000 );

    for ( $i = 1; $i <= $length; $i++ ) {
		$string	.=$conso[rand()%strlen( $conso )];
    }

    return $string;

}

echo random_string( 10 );

?>
Генераторы ПрограммированиеPHP