長く続いた夏の暑さもようやく峠を越え,秋の訪れとともに過ごしやすい日々となってきました,PHP 8.3の開発は順調に推移し,フィーチャーフリーズの後,ベータ版のリリースを経て,リリース候補版が公開されています.今回は,前回に続きPHP 8.3に向けて開発中の新機能の一部について紹介します.
PHP 8.3の開発状況
2023年7月18日に予定通りフィーチャーフリーズが行われ,PHP 8.3に採用される機能および変更点が確定しました.この先のプロセスは,テストを繰り返しながら11月23日に計画されているPHP 8.3.0の正式公開に向けてバグだしを行いつつ,安定化させていくプロセスとなります,その後,7月20日から2週間に1回のペースでベータ版が合計3回リリースされ,基本的な動作に問題がないことが確認されました.8月31日にリリース候補第1版(RC1)がリリースされ,その後,2週間に1回のペースでリリース候補版が公開されています.計画では,11月9日までに合計6回のリリース候補版が公開され,問題がないことが確認されれば,11月23日に正式公開となります.
以下,前回に続いて,PHP 8.3向けに実装済みの機能を順番に紹介していきます.
アトリビュートによるオーバーライト指定
オブジェクト指向開発では,サブクラスで親クラスのメソッドをオーバーライトとして固有の処理を実装することが度々行われます.例えば、以下の簡単なコードを見てみましょう.
<?php
class Foo {
protected function show(): void {}
}
class Moo extends Foo {
public function show(): void { print("Hello");}
}
ここでは,FooクラスのサブクラスとしてMooクラスを作成し,showメソッドをオーバーライトして処理を実装しています.
ここで,Mooクラスの実装後に親クラスFooの仕様が変更され,以下のように showメソッドの名前がshowItemに変更されたケースを想定してみましょう.別の変更として,showメソッドのシグニチャ(引数の仕様)が変更されるケースもあり得ます.
<?php
class Foo {
protected function showItem(): void {}
}
class Moo extends Foo {
public function show(): void { print("Hello");}
}
この場合、サブクラスであるMooの仕様も変更する必要がありますが、PHPのコードとしては正しいため,誤りに気が付くのが遅れる可能性があります.
PHP 8.3以降では,このようなミスマッチを生じるケースの検出を容易にするために,オーバーライトを行うメソッドに専用のアトリビュートとして #[\Override] を付加することができるようになります.具体的には以下のようになります.
<?php
class Foo {
protected function show(): void {}
}
class Moo extends Foo {
#[\Override]
public function show(): void { print("Hello");}
}
この場合,継承元のメソッドの仕様(名称やシグニチャ)が変更されると、以下のように以下のような致命的なエラーを発生し,簡単に検出することができるようになります.
Fatal error: Moo::shows() has #[\Override] attribute, but no matching parent method exists
PDOドライバ固有のサブクラスを導入
PHP Data Objects (PDO)は,統一されたデータベースへのインターフェイスを提供する標準エクステンションとして広く利用されています.PDOは主要なデータベースとの接続をサポートしており,各データベースとのインターフェイスは対応するデータベース用のドライバとして実装されています.PDOを利用する際には,まず,PDOのクラスのインスタンスを作成し,その際,第一引数にデータベースの種類などのパラメータを含むDSNを指定します.例えば,SQLiteデータベースに接続する場合は以下のようになります.
$db = new PDO('sqlite::memory:');
PHP 8.2までのPDOの利用法は,このようにデータベースの種類によらずPDOクラスのインスタンスを生成するというものでした.
データベース固有の機能を利用する際には,個々のデータベース固有のドライバに実装された関数を呼び出す必要があります.例えば,SQLite用のコールバック関数を作成する場合は,以下のように sqliteCreateFunction()メソッドをコールします.
$db->sqliteCreateFunction($function_name, $callback);
PDOは,データベースによらず統一化されたインターフェイスを提供していますが,上記のようにデータベース名を冠するメソッドが存在することで,可読性が損なわれる可能性があります.このため,PHP 8.3のPDOでは,データベース固有の機能をよりわかりやすく実装するために,以下のような変更が行われました.
- ドライバ固有の機能をサポートするPDOのサブクラスを定義
- ドライバ固有のサブクラスを返す静的ファクトリメソッド PDO::connectを定義
ドライバ固有のサブクラスは,PDOがサポートする各ドライバについて定義されます.例えば,SQLite用のサブクラスは,PdoSqliteとなります.
$db = new PdoSqlite($dsn, $username, $password, $options);
このクラスのインスタンスを直接生成することもできますが,静的ファクトリメソッド PDO::connect により生成することも可能です.
$db = PDO::connect($dsn, $username, $password, $options);
この場合,前記のデータベース固有の機能を実現する関数は以下のようにより汎用的な名前で定義することができます.
$db->create_function($function_name, $callback);
なお,$db = new PDO($dsn, …) によりインスタンスを生成した場合の動作は,従来と同様となります.従来の PDO::sqliteCreateFunction() のようなメソッドも引き続き利用可能ですが,将来的に廃止対象となる可能性もあります.
PDOは,データベース接続に関する標準インターフェイスとして多くの場面で利用されており,既存の応用事例も多いため,短期的に新しいインターフェイスに移行することは難しいと思われますが,データベース固有の機能を使うことは度々行われており,より可読性の良いコードを記述するために徐々に普及していくものと思われます.
INIファイルで環境変数参照時のデフォルト値
PHP では,PHP自体の動作を定義するパラメータをINIファイル(デフォルト:php.ini)と呼ばれるパラメータファイルに記述し,PHPの実行時に読み込みます.
INIファイルの内部では,システムの環境変数を参照することができます.例えば,以下の二つのパラメータ(session.name と sendmail_from )を環境変数(SESSION_NAME,MAIL_FROM_USER,MAIL_FROM_DOMAIN)から定義するコードは以下となります.
session.name = ${SESSION_NAME}
sendmail_from = "${MAIL_FROM_USER}@${MAIL_FROM_DOMAIN}"
この際,指定する環境変数が実行するシステムで定義されていない場合には,空文字列が使用されていまいます.PHP 8.3以降では,指定する環境変数が定義されていない場合に,フォールバックとしてデフォルト値を指定することができるようになりました.
具体的には,”:-” に続きデフォルト値を表す文字列を指定できます.
session.name = ${SESSION_NAME:-Foo}
sendmail_from = "${MAIL_FROM_USER:-info}@${MAIL_FROM_DOMAIN:-example.com}"
上記の例では,session.name ,MAIL_FROM_USER,MAIL_FROM_DOMAINのデフォルト値をそれぞれ Foo,info,example.com に指定しています.環境変数を指定しない状況で,以下のPHPコードを実行すると,出力は “info@example.com” のようになります.
var_dump(ini_get('sendmail_from'));
運用するシステムの環境変数の不整合等によりINIファイルの設定の不備を発生させないために,デフォルトをフォールバックとして設定できることは便利です.
今回は,前回に続いて,PHP 8.3で導入される予定の新機能の一部を紹介しました.次回以降もPHP 8.3の新機能を始め,PHP関連の話題を紹介いたします.