PHP界の重鎮、廣川類氏のコラム「PHPの最新状況:PHP 8.2に向けた開発が開始される」(第22回)

PHP

廣川類

PHP 8.2開発が始まり、新マイナーバージョンについての現状とユーザーに影響のある変更点を取り上げる。PHP Foundationが開発者を資金的にサポートし、PHPが安定して存在し続けることを目指している。また、演算子オーバーロードの導入は否決されたが、動的プロパティの廃止、ロケール非依存のケース変換、一部call_user_func()の廃止などが予定されている。これらの変更はPHPの可読性を向上し、安定性を保つためだ。

PHP8の最新版であるPHP 8.1.0が11月25日に正式リリースされた後,PHPの開発陣は次のマイナーバージョンであるPHP 8.2の開発を開始しました.本稿では,PHP 8.2における現時点での変更点を含むPHP関連の最新の状況について紹介します.

PHP Foundation設立の近況

 前回紹介したように,従来ボランティアとして無償でPHP関連の開発に貢献してきたPHP開発者を資金的にサポートするための非営利財団(NPO)として昨年の11月にPHPファウンデーション(https://opencollective.com/phpfoundation)が設立されています.PHPは世界中の多くのWebサーバーで運用され,その経済的な貢献は大きなものがありますが,PHPそのものはオープンソースとして開発されており,PHP自体を開発する中心的な開発者についてもなんら財政的なサポートは行われてきませんでした.PHPを利用する多くの企業においても,PHP自体が安定して存在し続けることが重要であり,PHPファウンデーションの趣旨には世界中から多くの賛同が集まっています.支援者側もPHPを利用する企業や個々の開発者までに様々であり,2022年1月末の時点で賛同資金は総額38万ドル(約4千万円)を超えています.現在,集まった賛同資金を原資として支援を行う開発者の選定を進めており,1月中を目標に契約文書の整備を完了した後,最初の支援先の開発者のリストを発表する予定とのことです.

今年の1月,著名なオープンソースライブラリcolors.jsやfaker.jsの作者であるMarak Squires氏が,自ら開発したソフトウエアが世界中の多くのWebブラウザで利用されているにも関わらず収入を生み出さないことに不満を感じ,意図的にライブラリーの最新版を正常に動作しない状態にさせたため,多くのユーザが影響を受けるという出来事がありました.この話はJavaScriptに関連するものであり,PHPそのものに関連する話題ではありませんが,他山の石とすべき出来事かもしれません.PHPファウンデーションによるPHP開発者支援の試みが開発者の生活を安定させることで,継続的で健全な開発コミュニティの維持・発展に貢献することが望まれます.

PHP 8.2の開発スケジュールと体制

 PHP 8.1が昨年末にリリースされた後,次のマイナーバージョンであるPHP 8.2に向けた議論が始まっています.ただし,1月時点ではまだPHP 8.2に向けた新機能は出揃っておらず,本格的な開発開始はもう少し先になる見込みです.今後,リリースマネージャの選定(選挙)が行われ,リリースに向けたスケジュールが決定される予定です.以下,PHP 8.2における現時点での変更点および議論について紹介します.

演算子オーバーロード

 PHP 8.2の大きな目玉となりうる機能として「演算子オーバーロード」の投票が1月に行われましたが,21対24で否決されており,現時点では実装されない見込みです.演算子オーバーロードはユーザ側で演算子(+など)の定義を上書きし,クラスオブジェクトなどにおいて四則演算などを可能とするものです.Pythonにおけるnumpyなどが代表的な実装例となりますが,任意精度演算や行列・ベクトル演算などの数値計算を行う際の記述を大幅に簡略化してくれる仕組みとして,有用と考えられます.今回提案された実装は,複雑になりがちな演算子オーバーロード機能の実装を比較的シンプルに行うよう工夫されたものでしたが,主要な開発者に受け入れられるまでには至らなかったようです.今後,設計の見直しを行った上で再度提案される可能性があります.PHPを利用するユーザで数値計算を多用するユーザがどの程度いるかは未知数ですが,行列・ベクトル演算を行う一部のユーザにとっては有用な機能と言えるでしょう.

動的プロパティの廃止

PHPにおいては,クラスオブジェクトのプロパティ変数にアクセスした際,クラス宣言において定義されていない変数である場合でも,定義が自動的に生成され,値が保存されます.この仕様はコーディング量を減らしてくれるため便利なのですが,タイポ(入力ミス)の際に意図せずに誤った変数に値が入力されてしまうなどのリスクが生まれます.例えば,以下の例を見てみましょう.

<?php
class Foo {
    public $item;
}
 
$moo = new Foo;
$moo->item = "orange";
$moo->iten = "apple";

 この例では,7行目は定義済みのプロパティ変数$itemに正しく値を代入していますが,8行目では変数名をitemではなくitenと間違えて入力しています.このため,$itemの値が更新されずに,新しいプロパティ変数$itenが作成されて値が入力されてしまいます.

 PHP 8.2では,このコードを実行すると以下のように動的プロパティが廃止されたとの警告が発生します.

Deprecated: Creation of dynamic property Foo::$iten is deprecated

 PHP 8.2では下位互換性確保のため,まだ,警告を発生するだけですが,次のメジャーバージョンであるPHP 9.0ではこの動的プロパティ生成機能は廃止され,使用時にエラーとなる予定です.クラスを定義する際に使用するプロパティ変数を予め定義しておくことで,このようなエラーを回避することができます.古いPHPスクリプトの一部にこのようなコードが残っている可能性もありますが,PHP 9.0リリースまでには修正を行う必要があります.

ロケール非依存のケース変換

 日本語ではあまり馴染みがありませんが,欧米ではケース変換(大文字小文字変換)がロケールに依存することが問題となるケースがあります.例えば,以下のコードを実行してみましょう.このコードは,バイト列「0xfc」(ドイツ語のuウムラウト:ü)を大文字に変換して16進ダンプするコードです.

<?php
setlocale(LC_ALL, 'C');
var_dump(bin2hex(strtoupper("\xfc"))); 

PHPのバージョンによらず”fc”が出力されます.
次にドイツ語のロケールを設定して同じコードを実行してみましょう.

<?php
setlocale(LC_CTYPE, "de_DE","de-DE");
var_dump(bin2hex(strtoupper("\xfc"))); 

PHP 8.1および以前のバージョンでこのコードを実行すると,”dc”( ドイツ語のUウムラウト:Ü)が出力されます.この変換(ウムラウト付文字を大文字に変換)はドイツ語としては正しいのですが,ロケールに依存して動作が変わることにより,不具合の原因となる可能性があります.

PHP 8.0より以前のバージョンでは,環境に依存したロケール参照が行われていましたが,PHP 8.0では標準であるCロケールがデフォルトとなっており,動作の差異が少なくなっています.ただし,上記のように明示的にsetlocaleによりロケールを指定された場合,従来のようにロケール依存で動作が変わる仕様となっています.

 PHP 8.2では,何らかの理由によりsetlocaleによりロケールを指定した場合でも,大文字小文字変換の結果が変わらないように仕様が変更されます.これにより,上記の問題は解消されると期待されます.既存の動作仕様に依存するコードの一部は書換る必要がありますが,すでにmbstring等で同様の機能が提供されているため,書換は容易とのことです.

部分的にサポートされているcallableの廃止

 現在,変数により動的に定義される関数(メソッド)をコールする手段としては,以下の2種類がサポートされています.

  1. call_user_func($callable)
  2. $callable()

 今回の提案は,1番目の手法でのみサポートされている関数(メソッド)コール手段を廃止するというというものです.この提案は,動作を統一することでコードの可読性を向上させることが目的です.

 具体的には,以下のような構文でcallableを生成した場合,PHP 8.2では,警告が発生するようになります.これらの構文は次のメジャーバージョン(PHP 9.0)で廃止される予定です.

“self::method”

“parent::method”

“static::method”

[“self”, “method”]

[“parent”, “method”]

[“static”, “method”]

[“Foo”, “Bar::method”]

[new Foo, “Bar::method”]

 では,例を見てみましょう.以下は,Fooクラスのメソッドshow()をスタティックコールする例です.

<?php
class Foo {
    public static function sayHello(): void {
        echo "Hello!";
    }
    public static function show(): void {
        $callable =  "self::sayHello";
        call_user_func($callable);
    }
}
Foo::show();

 このスクリプトをPHP 8.1または以前のバージョンで実行すると,”Hello!”と出力されます.

ここで,8行目を $callable() で置き換えると,以下のようにクラス”self”が見つからないというエラーが発生します.

Fatal error: Uncaught Error: Class “self” not found

 つまり,上記のスクリプトは,call_user_func()で関数(メソッド)コールを行った場合にのみ動作する例となっています.

一方,上記のスクリプトをPHP 8.2で実行すると,call_user_func()関数によリコールした場合でも,以下のように”self”を利用してコールを行ったことに関する警告が発生します.

Deprecated: Use of “self” in callables is deprecated

 この例では,8行目を例えば以下のように書き換えることで,どちらのコール方法でも動作するようになります.

$callable = self::class."::sayHello";

 前記のように,現状,2種類の関数コール方法のうちでcall_user_func()のみで利用できる構文が複数ありますが,一貫性を保つためにいずれも廃止されます.具体的には,PHP 8.2で警告が発生,次のメジャーバージョン(PHP 9.0)で廃止されますので,注意してください.

 今回は,次のマイナーバージョンアップにあたるPHP 8.2で予定される変更点について紹介しました.まだ,PHP 8.2の開発は本格化しておらず,今後,RFCにおける機能提案・投票を経て,いくつかの有用な機能が追加されると思われます.次回以降もPHP開発関連の話題を中心に紹介していきたいと思います.

<< PHP重鎮の廣川類氏のコラム「PHPの最新状況:PHP 8.1ついにリリースされる(第21回)」PHPの最新状況:PHPの重大なセキュリティ欠陥の修正版リリース(第23回) >>

関連記事

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

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

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

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

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