乱数発生の変更
PHPにおける乱数発生の実装は、長らく問題とされてきました。例えば、以下のような問題です。
- メルセンヌツイスタ(1996年に発表された疑似乱数発生器)がいまだに利用されている
- 状態がグローバルな領域に保持されている(メルセンヌツイスタの利用に由来)
- 奇数ばかりが出るなどランダム性が不完全である
大きなものは、状態がグローバルな領域に保持されているということで、これにより外部ライブラリで乱数の発生が不安定になったりしていました。
そこで、PHP 8.2ではRandom\Randomizerクラスが導入されました。このクラスのインスタンスでは、乱数発生エンジンを指定できるようにして、上記のような問題を解決しています。以下のリストは、乱数発生エンジンにRandom\Engine\Secureを使用した乱数発生の例です。
$engine = new Random\Engine\Secure(); $randomizer = new Random\Randomizer($engine); printf("%d\n", $randomizer->getInt(1, 10)); // mt_rand()の置き換え printf("%s\n", bin2hex($randomizer->getBytes(10))); // random_bytes()の置き換え $ary = $randomizer->shuffleArray([1, 2, 3]); // shuffle()の置き換え foreach ($ary as $a) { printf("%d ", $a); } printf("\n"); printf("%s\n", $randomizer->shuffleBytes('abc')); // str_shuffleの置き換え
実行結果は下記です。乱数なので、実行するたびに結果は変化します。getBytesメソッドの戻り値はそのまま表示すると文字化けすることもあるので、bin2hex関数で16進表記に変換しています。
6 d29dd26d1448477882fa 1 2 3 bac
なお、shuffleBytesメソッドはPHP 8.2の策定当初はshuffleStringメソッドとして実装されていましたが、shuffleStringメソッドはマルチバイト文字列には対応していないので、動作を正確に表した名称に策定途中で変更されました。
関数の細かな変更
関数単位でも、細かな変更が実施されました。
ロケール非依存の関数[8.2]
strtolowerなどの文字種に関連する関数は、字種の判定をロケールに依存していました。strtolower関数はアルファベットを小文字に変換しますが、アルファベットであるか?という判定はロケールに依存していました。
例えば、ウムラウトA(Ä)が変換されるかということはロケールに依存しており、ロケールによって挙動が変わるのは危険と見なされました。そこで以下の関数は、常にCロケールに基づく動作に変更され、具体的にはASCII文字に対してのみ作用します。ロケールによって挙動が変わらず、安全に利用できるようになりました。
- strtolower、strtoupper
- stristr、stripos、strripos
- lcfirst、ucfirst、ucwords
- str_ireplace
Cロケール
CロケールとはPOSIXロケールとも呼ばれ、POSIXに準拠した環境のデフォルトロケールを意味します。ロケールとはある環境における国や言語に関連する一連の設定を指し、CロケールのCはC言語の規格で定められたロケールです。
utf8_decodeとutf8_encodeを削除[8.2]
UTF-8文字列のデコードとエンコードのために、utf8_decode関数とutf8_encode関数があります。しかし、これらの関数の動作はLatin-1(ISO-8859-1)しか想定していません。他の処理系にもある似たような名称の関数と挙動が異なることで紛らわしいとして、PHP 8.2ではmb_convert_encoding関数の利用へ一本化することになりました。もともと、日本ではISO-8859-1のみを想定しているということは少ないので、影響は少ないと思われます。
iterator_*がiterable型の受け入れを可能に[8.2]
iterator_to_array関数とiterator_count関数は、その名称にそぐわずにiterable型を受け入れることはできませんでした(Traversalインタフェースを実装した型のみ受け入れ可能)。PHP 8.2では、iterable型を受け入れ可能になり、array型もこれらの関数に渡すことができます(iteratable型はarray型とTraversable型のUNION型であるため)。