PHPの重鎮廣川類氏のコラム「PHPの最新状況:PHP 8.1で導入される新機能(第20回)」

PHP

廣川類

今秋開催予定のPHPカンファレンス2021では、PHP 8.1の新機能が紹介されます。今回新たに実装される機能には、クラス定数のfinal指定、引数のデフォルト値のnewによるインスタンス生成、高速ハッシュ関数の適応などがあります。また、安全性の向上に対する取り組みとして、ENT_QUOTES/SUBSTITUTEが標準化されます。更なる詳細は、PHPカンファレンス2021のシンポジウムで解説される予定です。

今年も国内最大級のPHP関連イベントであるPHPカンファレンス 2021が10月2日~3日の二日間にわたり開催されます.昨今の状況から昨年に続き今年もオンラインで開催されます.このカンファレンスでは,40件以上の発表が行われ,PHP関連の最新の情報を得る良い機会となるはずです.いよいよリリースが近くなってきたPHP 8.1関連の話題も提供される予定です.本稿では,前回に引き続きPHP 8.1における変更点について紹介します.

PHP 8.1の開発スケジュール

PHP 8.1の開発では,7月20日にフィーチャーフリーズが行われた後,7~8月にベータ版,9~11月にリリース候補版のリリースが予定されています.本稿執筆時点では,9月16日にリリースされたリリース候補2版(RC2)が最新となっています.このまま開発が順調にいくと,正式版が11月25日にリリースされる予定です.

finalクラス定数

 PHPでは,クラスの定義において定数(クラス定数)を定義することができます.従来,このクラス定数の値を子クラスで書き換えることができました.以下のコードを見てみましょう.

 PHPでは,クラスの定義において定数(クラス定数)を定義することができます.従来,このクラス定数の値を子クラスで書き換えることができました.以下のコードを見てみましょう.

<?php
 class Foo {
     public const X = "foo";
 }
 class Bar extends Foo {
     public const X = "bar";   # 書き換え可能
 }

 ここでは,Fooクラスの子クラスとしてBarクラスを定義し,クラス定数Xの定義を書き換えています(6行目).

 PHP 8.1では,クラス定数の定義時にfinal指定子を指定することができるようになります.これにより,子クラスでクラス定数の値を書き換えることはできなくなります.上のコードにfinal指定子を追加してみましょう.

<?php
class Foo {
     final public const X = "foo";   # final指定
}
class Bar extends Foo {
     public const X = "bar";   # エラー発生
}

この場合,子クラスBarの定義においてクラス定数の値を書換えようとした際(6行目),エラーを発生します.この機能により,意図に反した定数の書き換えを防止することができます.

newによる引数デフォルト値指定

 クラスメソッドの引数において,デフォルト値を指定することができます.しかし,従来,オブジェクトを引数のデフォルト値として指定することはできませんでした.このため,以下のようにいったんnullを指定した上で,メソッドの中でnewによりインスタンスを作成し,代入する必要がありました.

class Test { 
    private Logger $log;
    public function __construct(?Logger $log = null) {
        $this->log=$log ?? new NullLogger;
    }
}

PHP 8.1では,引数のデフォルト値の指定時にnewによるクラスインスタンス生成が可能となります.上のコードは以下のようにシンプルに記述できるようになります.

class Test { 
    public function __construct(private Logger $log = new NullLogger) {}
}

 この例では,コンストラクタにおいて,プライベート変数としてLoggerクラスの変数$logを定義し,NullLoggerクラスのインスタンスを代入しています.

高速ハッシュ関数

 PHPでは,非暗号学的ハッシュ関数hashにおいて,ハッシュのアルゴリズムを指定できます.PHP 8.1では,現時点で最速のアルゴリズムの一つであるMurmurHash3およびxxHashを指定できるようになります.

 MurmurHash3によりハッシュ値を求める例を以下に示します.


$hash=hash('murmur3f', $content);

 hash関数の第一引数にハッシュ関数のアルゴリズム(’murmur3f’),第二引数にハッシュ値を求めるコンテンツを指定すると,ハッシュ値が返されます.

 ハッシュ値を求めるアルゴリズムのベンチマークの例として,単位時間に実行できる回数を下図に示します(環境:Ryzen 5 2400G, Ubuntu 20.04).ここでは,sha256関数を1として正規化しています.

Sha256に比べてNurmurHash3関数は6~8倍,xxHash関数は9~12倍高速であることがわかります.

ENT_QUOTES/SUBSTITUTE標準化

 PHP 8.1では,HTML関連の関数htmlentities(),htmlspecialchars()において,ENT_QUOTESおよびENT_SUBSTITUTEが標準オプションとして指定されるようになります.これにより,シングルクォート(’)および無効な文字が自動的に安全な文字エンティティに変換されます.

以下のコードを見てみましょう.

<?php
$str = "A 'quote' is <b>bold</b>";
echo htmlentities($str);

従来のPHPでは,オプションを指定しないhtmlentities関数では,以下のようにシングルクォートが変換されず,そのまま出力されます.

A 'quote' is &lt;b&gt;bold&lt;/b&gt;

PHP 8.1では,オプションを指定しない場合でも以下のようにシングルクォートがHTMLエンティティに変換されます.

A &#039;quote&#039; is &lt;b&gt;bold&lt;/b&gt;

次に無効な文字コードを指定した場合を考えます.以下のコードでは文字列$strに無効な文字コード(\xff)を指定しています.これは不正な文字を挿入し,これを処理系が削除することで不正な文字列を出現させるセキュリティ攻撃に関するコードです.

<?php
$str = "java\xffscript:alert('XSS')";
echo htmlentities($str);

従来のPHPでは,文字列に無効な文字が含まれると文字列全体が出力されませんでした.PHP 8.1では,無効なコードをUnicodeの置換文字(U+FFFDまたは&#FFFD;)に置換するオプションENT_SUBSTITUTEが標準で指定されるようになります.出力は以下となり,無効なコードが‘�’で置換されます.

java�script:alert(&#039;XSS&#039;)

 今回は,PHP 8.1における機能強化のポイントについて紹介しました.PHP 8.1のリリース候補版のテストに参加いただき,これらの機能を試していただければと思います.

<< PHP重鎮の廣川類氏によるコラム「PHPの最新状況:PHP 8.1の開発がいよいよ最終段階に(第19回)」PHP重鎮の廣川類氏のコラム「PHPの最新状況:PHP 8.1ついにリリースされる(第21回)」 >>

関連記事

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

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

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

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

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