Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】Random\Engine::generate()メソッドの使い方

generateメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

generateメソッドは、PHP 8で導入された新しい乱数生成機能の基盤となるRandom\Engineに属し、暗号学的に安全な乱数のバイト列を生成するメソッドです。このメソッドは、より高レベルな乱数生成器が利用するための、予測不可能な生の乱数データを提供することを主な目的としています。

generateメソッドは引数を取りません。呼び出されるたびに、実装されている乱数生成アルゴリズムに基づいて、固定長のバイナリ文字列を返します。このバイナリ文字列は、ランダムなバイトの連続であり、それ自体が直接的に特定の数値や結果として利用されることは稀です。むしろ、この生のバイト列は、Random\Randomizerなどの上位クラスや、様々な形式(整数、浮動小数点数、シャッフルされた配列など)の乱数を生成する他の関数やメソッドの入力として活用されます。

システムエンジニアを目指す上で、このgenerateメソッドを直接利用する機会は少ないかもしれませんが、PHPのセキュアな乱数生成機構の根幹を支えていることを理解することは重要です。これにより、パスワード生成、セキュリティトークンの発行、またはゲーム内のランダム性など、信頼性とセキュリティが求められるアプリケーションにおいて、その乱数の出所と仕組みを把握し、より安全なシステムを構築するための知識を得ることができます。これは、多様な乱数生成エンジンを統一的に扱うためのインターフェースを提供し、将来的な拡張性にも貢献しています。

構文(syntax)

1<?php
2$engine = new Random\Engine\Xoshiro256StarStar();
3$randomBytes = $engine->generate();

引数(parameters)

引数なし

引数はありません

戻り値(return)

string

指定された長さ(バイト数)のランダムなバイナリ文字列を生成して返します。

サンプルコード

PHP Random\Engineでランダム文字列を生成する

1<?php
2
3// PHP 8.2 以降で利用可能です。
4
5/**
6 * Random\Engine::generate メソッドを使用して、指定された長さのランダムな英数字文字列を生成します。
7 *
8 * 注意: 提供されたリファレンス情報では Random\Engine::generate メソッドは引数なしとありますが、
9 * 実際のPHPの公式ドキュメントでは int $length 引数を受け取ります。
10 * このサンプルコードは、実際に動作するPHPの仕様に基づき、引数を指定しています。
11 *
12 * @param int $length 生成する文字列の長さ。
13 * @return string 生成されたランダムな英数字文字列。
14 */
15function generateRandomAlphanumericStringFromEngine(int $length): string
16{
17    // 暗号学的に安全なランダムエンジンをインスタンス化します。
18    // Random\Engine は抽象クラスなので、Random\Engine\Secure のような具体的な実装クラスを使用します。
19    $engine = new Random\Engine\Secure();
20
21    // ランダム文字列に含める文字セットを定義します。
22    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
23    $charactersLength = strlen($characters);
24    $randomString = '';
25
26    // Random\Engine::generate メソッドはランダムなバイト列を生成します。
27    // ここでは、指定された文字列の長さと同じバイト数のランダムデータを取得します。
28    $randomBytes = $engine->generate($length);
29
30    // 取得したバイト列の各バイトを基に、文字セットからランダムに文字を選びます。
31    for ($i = 0; $i < $length; $i++) {
32        // ord() は文字のASCII値(バイト値)を返します。
33        // これを文字セットの長さで割った余りを使ってインデックスを決定します。
34        $index = ord($randomBytes[$i]) % $charactersLength;
35        $randomString .= $characters[$index];
36    }
37
38    return $randomString;
39}
40
41// 例: 12文字のランダムな英数字文字列を生成して表示
42$randomStringExample = generateRandomAlphanumericStringFromEngine(12);
43echo "生成されたランダムな英数字文字列: " . $randomStringExample . PHP_EOL;
44
45// 別の長さで試すことも可能です。
46$anotherRandomString = generateRandomAlphanumericStringFromEngine(18);
47echo "別のランダムな英数字文字列: " . $anotherRandomString . PHP_EOL;

このPHPのサンプルコードは、PHP 8.2以降で導入されたRandom\Engine::generateメソッドを利用して、暗号学的に安全なランダムな英数字文字列を生成する方法を示しています。

まず、ランダム値を生成するためにRandom\Engine\Secureというクラスをインスタンス化しています。これはRandom\Engine抽象クラスの具体的な実装であり、高いセキュリティが求められる場面に適したランダムな値を提供します。

Random\Engine::generateメソッドは、引数として生成したいランダムなバイト列の長さを整数で受け取ります。提供されたリファレンス情報では引数なしとされていますが、PHPの実際の仕様では、この引数が必要です。このメソッドは、指定された長さのランダムなバイト列を文字列として返します。このバイト列はそのままでは一般的なランダム文字列として利用しづらいため、サンプルコードではこれを加工しています。

コードでは、「0-9、a-z、A-Z」の文字セットを定義し、generateメソッドで得たランダムなバイト列を基に、この文字セットから一文字ずつランダムに選び出して連結することで、指定された長さの英数字文字列を作成します。具体的には、バイト列の各バイト値を文字セットの長さで割った余りをインデックスとして利用し、対応する文字を選び出しています。

引数$lengthは、最終的に生成したいランダムな英数字文字列の長さを整数で指定します。この関数が返す戻り値は、その$lengthで指定された文字数を持つ、安全なランダム英数字文字列です。この仕組みにより、予測が困難な文字列が必要な場面で、信頼性の高いランダムな値を簡単に利用できます。

PHP 8.2以降で利用可能です。提供されたリファレンス情報ではRandom\Engine::generateが引数なしと記載されていますが、実際のPHPの仕様では通常、生成するバイト列の長さを引数として受け取ります。このサンプルコードは、実際のPHPの仕様に沿って引数を使用していますのでご注意ください。

Random\Engineは抽象クラスであるため、new Random\Engine()のように直接インスタンス化はできません。サンプルコードのように、Random\Engine\Secureといった具体的な実装クラスを使用する必要があります。

generateメソッドはランダムなバイト列を返します。このバイト列はそのままでは人間が読める意味のある文字列ではないため、サンプルコードのように、使用したい文字セット(英数字など)に変換・マッピングする処理が必要です。この手法を用いることで、暗号学的に安全なランダム性を持つ、指定された文字種の文字列を生成できます。これにより、セキュリティが求められる場面でも信頼性の高いランダム文字列を利用できます。

PHP generateUuidV4を生成する

1<?php
2
3/**
4 * プログラミング言語リファレンス情報に合わせるため、
5 * Random\Engine の generate() メソッドが引数なしで16バイトの文字列を返すと仮定したカスタムエンジンです。
6 * 実際のPHPのRandom\Engine実装(例: Random\Engine\Secure)のgenerate()は、
7 * 引数を取らずintを返し、直接UUID生成には使えません。
8 * このクラスは、提供されたリファレンス情報に基づく「もしそうであったなら」のデモンストレーションです。
9 */
10class CustomUuidEngine extends Random\Engine
11{
12    /**
13     * プログラミング言語リファレンス情報に従い、引数なしで16バイトの文字列を生成します。
14     * UUID生成に必要な16バイトのランダムなバイト列を返します。
15     *
16     * @return string 16バイトのランダムなバイト列
17     */
18    public function generate(): string
19    {
20        // PHPの標準関数random_bytesを用いて16バイトのランダムなバイト列を生成します。
21        return random_bytes(16);
22    }
23}
24
25/**
26 * プログラミング言語リファレンス情報で示されたRandom\Engineのgenerateメソッドを使用して
27 * UUIDバージョン4を生成します。
28 *
29 * この関数は、提供されたリファレンス情報(所属クラス: Random\Engine, 名前: generate,
30 * 引数: 引数なし, 戻り値: string)に合致するエンジンのgenerate()メソッドが、
31 * UUID生成に必要な16バイトのランダムな文字列を返すと仮定して実装されています。
32 *
33 * @return string 生成されたUUIDバージョン4の文字列
34 */
35function generateUuidV4WithCustomEngine(): string
36{
37    // リファレンス情報に合わせたカスタムエンジンをインスタンス化します。
38    $engine = new CustomUuidEngine();
39
40    // エンジンのgenerate()メソッドを呼び出し、16バイトのランダムなバイト列を取得します。
41    $bytes = $engine->generate();
42
43    // UUID v4のバージョン (4) およびバリアント (RFC 4122) に応じてバイトを調整します。
44    // バージョンバイト (6番目のバイト、0-indexed): 上位4ビットを0100 (4) に設定
45    $bytes[6] = chr((ord($bytes[6]) & 0x0F) | 0x40);
46    // バリアントバイト (8番目のバイト、0-indexed): 上位2ビットを10xx に設定
47    $bytes[8] = chr((ord($bytes[8]) & 0x3F) | 0x80);
48
49    // バイト列を16進数文字列に変換し、UUIDの標準フォーマット (8-4-4-4-12) に整形します。
50    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($bytes), 4));
51}
52
53// 例: UUIDを生成して出力
54echo generateUuidV4WithCustomEngine();
55echo "\n"; // 出力の視認性を高めるための改行

このPHPコードは、UUID(Universally Unique Identifier)バージョン4を生成するプロセスを示しています。ただし、このデモンストレーションは、Random\Engineクラスのgenerate()メソッドが「引数を受け取らず、16バイトの文字列を返す」という、提供されたプログラミング言語リファレンス情報に合致するように仮定して作成されています。実際のPHPのRandom\Engineの振る舞いとは異なる点にご注意ください。

コード内のCustomUuidEngineクラスは、この仮定されたリファレンス情報に適合させるために独自に定義されています。このクラスのgenerate()メソッドは、引数なしで呼び出され、PHPのrandom_bytes()関数を使って16バイトの安全なランダムなバイト列を文字列として返します。これがUUID生成の基盤となるランダム性を提供します。

generateUuidV4WithCustomEngine()関数は、このCustomUuidEngineのインスタンスを作成し、そのgenerate()メソッドを呼び出して16バイトのランダムな文字列を取得します。次に、取得したバイト列に対してUUIDバージョン4の標準的な形式に準拠するよう、特定のバイト(バージョンとバリアントを示す部分)を調整します。具体的には、バイト列の6番目と8番目のバイトを変更し、UUIDのバージョンが4、バリアントがRFC 4122に適合するように設定します。最後に、調整されたバイト列を16進数に変換し、UUIDの標準的な「xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx」のフォーマットに整形して、文字列として返します。このコードは、ランダムなバイト列から標準的なUUIDを生成する一連の変換手順を具体的に示しています。

このサンプルコードは、提供されたリファレンス情報の「戻り値:string」という前提に合わせて、Random\Engineを継承したカスタムクラスを実装しています。しかし、実際のPHP 8のRandom\Engine::generate()メソッドは、引数を取らずintを返すため、そのままではUUID生成には使えません。実際に安全なUUIDを生成する場合は、PHP標準のrandom_bytes()関数を使うか、PHP 8.2以降であればRandom\RandomizerクラスのgetBytes()メソッドを利用するのが適切です。このコードは、Random\Engineを拡張し、カスタムの乱数生成ロジックを実装する際の考え方を学ぶ良い例となります。

関連コンテンツ