PHP重鎮 廣川類氏のコラム第24回「PHPの最新状況:PHP 8.2開発本格スタート」

  • 2022.06.06
  • PHP
PHP重鎮 廣川類氏のコラム第24回「PHPの最新状況:PHP 8.2開発本格スタート」

暑さを感じる日々も多くなってきました.次のマイナーバージョンであるPHP 8.2に関して,リリースマネージャが決まるなど,開発が本格化しています.

本稿では,主にPHP 8.2の開発体制と提案されている機能の紹介を行います.

PHP Foundationにおけるサポート対象の開発者が決まる

本連載(21回,22回)で紹介したPHP開発者を支援する団体The PHP Foundationにおいて,支援対象となる開発者の選定が行われていましたが,第一弾として6名の開発者が選定されました.選定された開発者には,PHP本体の開発に必要な時間的リリースを確保するための資金が提供されます.前記6名には,将来のコア開発者を育成する目的で,比較的知名度が低い開発者も含まれますが,注目すべきはPHPのコア開発者であるDerick Rethans氏が含まれていることです.同氏が従来以上にPHPコア開発に従事できるようになることで,PHPの開発の加速・安定化が期待できます.なお,同氏は同団体の運営に参加していましたが,支援対象となったことで,運営からは外れています.

PHP 8.2のリリースマネージャと開発スケジュールが決まる

 PHP 8.2のリリースマネージャが,投票によりPierrick Charron氏とSergey Panteleev 氏の2名に決まりました.また,PHP 8.1のリリースマネージャであるBen Ramsey氏がメンターとしてリリースマネージャをサポートすることになりました.

 リリースに向けた開発スケジュールも定義されました.リリース予定日は,2022年11月24日となっています.これに向けて,まず,6月以降α版をリリースし,7月19日にFeature freeze(リリース版に採用する機能を決定する)を行います.PHP 8.2に新規に採用される機能は,この時点までに決定されます.この後は,機能を安定化させるフェーズとなり,7月21日以降にベータ版,9月からリリース候補版をそれぞれ複数回リリースして,バグを取り除いた後,正式リリースとなります.なお,リリース日を含む開発スケジュールは,開発の進捗により変わる可能性があることに注意してください.

 以下,前回までに引き続きPHP 8.2で採用される予定の新機能および変更点について紹介します.

 

動的プロパティの廃止(https://wiki.php.net/rfc/deprecate_dynamic_properties)(補足)

動的プロパティの廃止については,本連載の22回で紹介しました.従来のPHPでは,あるクラスにおいて宣言されていないプロパティに値が代入されると,自動的に指定したプロパティが作成されるという動作でした.このような動作は,変数名のタイポなどにより予測しない動作を誘発するリスクがあるため,将来的に廃止されます.具体的には,動的プロパティ生成機能は,PHP 8.2でDeprecated(廃止)という警告を発生する動作となり,PHP 9.0以降で廃止(ErrorExceptionがスローされる)されます.

この変更が適用されると,動的プロパティを利用する既存のコードにおいて警告が発生する可能性があります.将来的には,コードを修正することが望ましいと言えますが,移行期における一時的な回避策が用意されていますので,紹介します.

まず,廃止される機能(Deprecated)に関する警告を抑止する一般的なPHPの機能としては,PHP設定オプションerror_reportingをphp.ini等に置いて指定するというものがあります.例えば,以下のように指定すると,E_DEPRECATEDに属する警告は発生しなくなります.

error_reporting(E_ALL ^ E_DEPRECATED);

なお,この回避策は,PHP 9.0以降この機能がエラー扱いになった際には適用されず,あくまでもPHP 8.2における暫定的な対策であることに注意してください.

PHP 9.0以降も利用できる別の回避策として,クラスの定義の前に#[AllowDynamicProperties] というアノテーションを指定するという手段が提供されています.この指定を追加することにより,指定したクラスおよびその派生クラスで動的プロパティを利用できるようになります.以下のコードでは,動的プロパティを7行目で利用し,変数 iten に値を代入する際に自動的に変数iten が生成されます.

<?php // https://wiki.php.net/rfc/deprecate_dynamic_properties
class Foo {
    public $item;
}
 
$moo = new Foo;
$moo->item = "orange";
$moo->iten = "apple";

このコードは,PHP 8.2以降では,以下のような警告を発生します.

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

 ここで,以下のように属性 #[AllowDynamicProperties] をクラス定義の前に追加してみましょう.

#[AllowDynamicProperties]
class Foo {
    public $item;
}

 これにより,指定したクラス(Foo)で動的プロパティが利用できるようになり,先程警告を発生したコードに置いても警告は発生しなくなります.

 なお,意図的な動的プロパティの代入・取得に従来から用いられている__getおよび__setメソッドにおいてアクセスされるプロパティは動的プロパティとみなされず,従来通り利用できます.例えば,以下のコードを見てみましょう.

<?php // https://wiki.php.net/rfc/deprecate_dynamic_properties
class Foo {
    private array $data = [];
    public function &__get($name) { return $this->data[$name];}
    public function __set($name, $value) { $this->data[$name]=$value;}
}
 
$moo = new Foo;
$moo->name = "taro";
print ($moo->name); // 出力: taro

9行目で未定義のプロパティ変数nameに値を代入していますが,__setメソッドを宣言しており,このメソッドにおいて自動的により指定した値がプロパティ配列dataに代入されるため,警告を発生せず,従来通りの動作となります.10行目で値を表示していますが,この際にも定義された__getメソッドが自動的にコールされ,配列dataから指定した変数の値が取得されるため,警告を発生せず,動作は従来通りとなります.

また,組込クラスのstdClassにおいては従来通り動的プロパティを利用できます.例えば,以下のコードはPHP 8.2以降でも警告を発生せず動作します.

<?php // https://wiki.php.net/rfc/deprecate_dynamic_properties
$moo = new stdClass;
$moo->name = "taro";
print ($moo->name); // 出力: taro

Readonlyクラス(https://wiki.php.net/rfc/readonly_classes)

 PHP 8.1では,クラスのプロパティにreadonly属性(読み込みのみ可能)を指定する機能がサポートされています.PHP 8.2では,クラス全体にreadonlyを指定することができるようになります.readonlyが指定されたクラスでは,コンストラクタ以外の場所でプロパティの値を変更できなくなります.例として,以下のコードを見てみましょう.

<?php // https://wiki.php.net/rfc/readonly_classes
readonly class Foo {
    public int $bar;
    public function __construct() {
        $this->bar = 1;
    }
}
$foo = new Foo();
$foo->bar = 2; // 致命的エラーを発生

 クラスFooはreadonly宣言が付与されているため,9行目でプロパティ変数barに値が代入された際に以下のような致命的エラーを発生します.

Fatal error: Uncaught Error: Cannot modify readonly property Foo::$bar

 次に,以下のように未定義のプロパティ変数mooに値を代入して動的プロパティを作成してみましょう.

$foo->moo = 1;

通常のクラスでは,PHP 8.2において前述のように警告(Deprecated)を発生しますが,readonly指定されたクラスの場合,以下のように致命的エラーを発生します.

Fatal error: Uncaught Error: Cannot create dynamic property Foo::$moo

なお,readonlyが指定されたクラスに先程紹介した#[AllowDynamicProperties]属性を指定することはできません.#[AllowDynamicProperties]を指定した場合,致命的なエラーを発生します.

また,プロパティ変数の宣言において,型宣言を省略したり,static宣言を行ったりすることはできません.上記の例の3行目を以下のように変更するといずれも致命的エラーを発生します.

[型宣言を省略]
    public $bar;
[static宣言を追加]
    public static int $bar;

また,クラス継承においても注意点があり,継承元と継承先のreadonly属性は一致している必要があります.つまり,readonly指定されたクラスを継承した場合,継承先のクラスにおいてもreadonly指定を行う必要があります.また,この逆として,readonly指定されていないクラスを継承した際に,継承先のクラスにおいてreadonlyを指定することはできません.

 例えば,以下のようなコードは,親クラスでのみreadonlyが指定されているため,致命的エラーを発生します.

readonly class Foo {}
class Moo extends Foo {}

 逆に以下のコードにおいては,子クラスでのみreadonlyが指定されているため,同様に致命的エラーを発生します.

class Foo {}
readonly class Moo extends Foo {}

 今回は,次のマイナーバージョンアップにあたるPHP 8.2の開発計画と予定される変更点について紹介しました.リリースマネージャおよびリリースに向けたスケジュールが決まったことでPHP 8.2の開発は本格化するものと思われます.PHP 8系の機能を更に進化させたPHP 8.2が年末に向けて予定通りリリースされることが期待されます.

PHPカテゴリの最新記事