PHP重鎮の廣川氏のコラム「ついに PHP 8.3に向けた開発始まる」(第29回)

PHP

廣川類

2023年に向けて開発が進むPHP 8.3の新機能を紹介。これまで制約があったクラス定数と列挙型の参照が変数により動的に可能となるほか、乱数生成用クラスRandomizerが拡張されます。具体的には、指定の文字集合からランダム文字列を生成するメソッドや、指定範囲乱数を生成するメソッドなどが追加。これによりコードの可読性向上と機能性強化が期待されます。

 2023年が始まり,早2ヶ月がたとうとしています.昨年12月にリリースされたPHP 8.2は,バグ修正版のリリースがほぼ毎月1回リリースされ,維持フェーズに移行しています.また,次のマイナーバージョンである PHP 8.3に向けた開発が徐々に進みつつあります.今回は,PHP 8.3に向けて開発中の新機能の一部について紹介します.

PHP 8.3の開発状況

 PHP 8.3のリリースに向けた工程はまだ正式に立ち上がっておらず,リリースに向けた開発工程を統率するリリースマネージャもまだ決まっていません.ただし,例年PHPのマイナーバージョンのリリースが11月末に行われていることから,PHP 8.3のリリース時期も同じ時期であると予想されます.また,テストバージョンのリリースは,α版,β版,リリース候補版と進んでいきますが,最初のテストバージョンがリリースされるのが,例年6月ごろとなっていますので,リリースに含まれる新機能の骨格がほぼ見えてくるのも同じ頃と予想されます.リリースマネージャの選挙は例年5月に行われているため,この頃から開発が本格化するものと思われます.

PHP 8.3の全体像が見えるようになるまでにはあと数ヶ月かかりますが,すでにPHP 8.3に含まれる予定のいくつかの機能が提案・採用され,すでに実装されていますので,順番に紹介していきます.

動的なクラス定数の取得

PHPでは,$foo->$barのようにクラスの要素(プロパティ,メソッド)を(定義が動的に変更される)変数で参照する機能がサポートされています.しかし,「クラス定数」についてはこの変数による参照が従来サポートされていませんでした.

 例えば,以下のコードを見てみましょう.

class Foo {
    public const NAME = "Taro";
}
$name = 'NAME';
echo Foo::{$name};

 ここでは,クラスFooの定数NAMEを変数$nameにより,Foo::{$name}のように参照しています.このような構文は,PHP 8.2までのバージョンではサポートされておらず,エラーになってしまいます.動的に定義した変数によりクラス定数を参照するためには,代わりに constant ()関数を利用して,以下のように参照する必要がありました.

echo constant("Foo::$name");

PHP 8.3以降では,より直観的にわかりやすい以下の構文によるクラス定数の参照が可能になります.

echo Foo::{$name};

 同様に,列挙型においてもcase文の選択肢の値を 列挙型名::{変数名}->valueのように,変数により動的に参照できるようになります.以下,具体的な例を見てみましょう.

enum Id: int {
    case Taro   = 1;
    case Hanako = 2;
}
$id = 'Hanako';
echo Id::{$id}->value; // 出力: 2

 ここでは,列挙型Idを整数値として定義し,’Hanako’を変数$idに代入して,参照しています.

 従来は,このような変数による直接的な参照はサポートされておらず,前記のクラス定数と同様,以下のようにconstant関数を用いる必要がありました.

echo constant("Id::$id")->value;

 PHP 8.3以降では,Id::{$id}->value のような参照が可能となり,コードの可読性が向上します.

乱数クラスの拡充

 PHP 8.2で追加された乱数生成用クラスRandomizerへの拡張として,3つのメソッド(getBytesFromString(),getFloat(),nextFloat())の追加が提案されました.

 まず,アルファベットや数字などの指定した文字集合から指定した長さのランダムな文字列を生成するgetBytesFromString()メソッドが追加されました.以下,例を見てみましょう.

$rng = new Random\Randomizer();
$s = 'abcdefghijklmnopqrstvwxyz0123456789';
print($rng->getBytesFromString($s, 6));

 上の例は,小文字のアルファベットと数値の組み合わせによる長さ6文字のランダムな文字列(例:19d8hr)を生成・出力します.具体的な用途としては,例えば,ランダムなパスワード文字列の生成があります.なお,この関数ではマルチバイト文字はサポートされていません.文字集合の各文字は同じ確率で選択されます.ある文字が選択される確率を上げたい場合,その文字を複数回記述します.例えば,”AAABC”とすると,’A’ が ’B’,’C’に比べて3倍多い確率で選択されます.

 次にgetFloat()メソッドについて紹介します.このメソッドは,最小値と最大値で指定された範囲の乱数を生成します.以下のコード例は,1と2の間の乱数(例:1.234)を出力します.

print($rng->getFloat(1,2);

引数には最小値と最大値を指定します.デフォルトの生成範囲は「最小値を含み最大値は含まない」範囲となります.この定義は,3番目の引数(オプション)により変更可能です.この引数には,Random\IntervalBoundaryの値を指定します.定義を表1に示します.

表1  Random\IntervalBoundaryの値と生成範囲

 最小値最大値
ClosedOpen含む含まない
ClosedClosed含む含む
OpenClosed含まない含む
OpenOpen含まない含まない

 例えば,以下のようにRandom\IntervalBoundary::OpenOpenを指定すると,指定した最小値と最大値は共に乱数の生成範囲に含まれません.この例の集合は,(1,2) のように記述されます.

$r = $rng->getFloat(1,2,\Random\IntervalBoundary::OpenOpen);

 オプション引数を指定しなかった場合のデフォルト値は,Random\IntervalBoundary::ClosedOpen となっており,最小値は乱数の生成範囲に含まれますが,最大値は含まれません.

 最後にnextFloat()メソッドについて紹介します.このメソッドの動作は,getFloat(0,1)に相当し,集合は[0,1) のように記述されます.

 以下の例は,[0,1)の範囲の乱数を出力します.

print($rng->nextFloat());

 今回は,PHP 8.3で導入される予定の新機能の一部を紹介しました.この他にもいくつかの機能が提案されており,本格的な開発が始まると予想される5月までに主な機能が出揃うと予想されます.次回以降もPHP 8.3の新機能を始め,PHP関連の話題を紹介いたします.

<< PHP重鎮の廣川氏によるコラム「PHPの最新状況:いよいよPHP 8.2 リリースへ」(第27回)PHP重鎮の廣川類氏によるコラム「PHPの最新状況:PHP 8.3の開発が本格化」(第30回) >>

関連記事

Webサイト運用の課題解決事例100選 プレゼント

Webサイト運用の課題を弊社プロダクトで解決したお客様にインタビュー取材を行い、100の事例を108ページに及ぶ事例集としてまとめました。

・100事例のWebサイト運用の課題と解決手法、解決後の直接、間接的効果がわかる

・情報通信、 IT、金融、メディア、官公庁、学校などの業種ごとに事例を確認できる

・特集では1社の事例を3ページに渡り背景からシステム構成まで詳解