> Indeed, the current implementation appears to have several problems. So,
> how about the following implementation?
>
> ```php
> interface RandomNumberGenerator
> {
> public function generate(): int;
> }
>
> final class Random
> {
> private RandomNumberGenerator $rng;
> public function __construct(?RandomNumberGenerator $rng = null)
> {
> $this->rng = $rng ?? new XorShift128Plus(random_int(PHP_INT_MIN,
> PHP_INT_MAX));
> }
> public function nextInt(): int {}
> public function getInt(int $min, int $max): int {}
> public function getBytes(int $length): string {}
> public function shuffleArray(array $array): array {}
> public function shuffleString(string $string): string {}
> public function __serialize(): array {}
> public function __unserialize(array $data): void {}
> }
>
> class XorShift128PlusNumberGenerator implements RandomNumberGenerator
> {
> public function generate(): int {}
> public function __serialize(): array {}
> public function __unserialize(array $data): void {}
> }
>
> class MT19937NumberGenerator implements RandomNumberGenerator
> {
> public function generate(): int {}
> public function __serialize(): array {}
> public function __unserialize(array $data): void {}
> }
>
> class SecureNumberGenerator implements RandomNumberGenerator
> {
> public function generate(): int {}
> }
> ```
>
> This is an approach similar to Nikita's `createDefault`. If the
> constructor has a null argument, it uses the default, XorShift128+,
> internally.
>
> Also, whether the Random class is serializable or clonable depends on the
> instance of RandomNumberGenerator being used. This means that when the
> Random class clone is called, the `$rng` member will be implicitly cloned.
>
> How about this?
>
Hello, thanks for thinking again.
A few editorial notes:
- I guess that would be "new XorShift128PlusNumberGenerator" (like the
class name)?
- The non-Secure implementations' stubs are probably missing `public
function __construct(?int $seed = null) {}`?
- The Random class' and non-Secure implementations' stubs are probably
missing `public function __clone(): void {}` (like `__serialize()`)?
That would let us use the API like this:
1. Construction: one of:
- default RNG and seed: `$random = new Random();`
- chosen RNG, default seed: e.g. `$random = new Random(new
MT19937NumberGenerator());`
- chosen RNG and seed: e.g. `$random = new Random(new
MT19937NumberGenerator(1234));`
(no "default RNG, chosen seed", but the default RNG can be documented,
and one could argue that a chosen seed only makes sense with a chosen RNG
anyway)
2. Usage: `$int = $random->nextInt();`, `$percent = $random->getInt(0,
100);`, `$dword = $random->getBytes(4);`, `$shuffledList =
$random->shuffleArray($list);` etc.
I think this is well-consistent with the "pure design" described by Nikita,
and I personally find it both flexible/extensible and easy-to-use =)
(Just beware that the namespace question will probably pop up again.)
PS: I feel like my numerous questions/suggestions (in this thread and the
previous ones) may also have caused some deviations, so I hope that I won't
need more and that other participants will reach a consensus...
Best regards,
--
Guilliam Xavier