6月も半ばとなり、梅雨入りの後で雨の日も増えています。PHPの次のマイナーバージョンであるPHP 8.5の開発が、8月のフィーチャーフリーズに向けて順調に進んでいます。本連載では、前回に引き続きPHP 8.5で強化される機能について紹介していきます。
OPcacheが標準組込みモジュールに
OPcacheは、PHP 5.5でPHPに組み込まれたキャッシュ用エクステンションです。OPcacheにより、コンパイル済みのPHPコードのキャッシュが可能となり、応用速度の向上に大きく貢献しています。OPcacheがPHPに組み込まれる前は、別パッケージとして配布されるキャッシュ用エクステンションをインストールする必要がありました。コードのキャッシュを行う機能の実装は大変複雑でPHPのスクリプト・エンジンの実装にも深く依存しているため、PHPのバージョンが更新されてスクリプト・エンジンであるZendEngineの実装が変更されると使用できなくなる場合がありました。OPcacheがPHP本体に同梱されるようになったことで、このようなバージョン間の互換性に関する問題が解消され、安定して動作するキャッシュ機能を利用することができるようになりました。OPcacheは、オプティマイザによる最適化もサポートしています。
PHP 8.0において、JIT (Just-in-Time)コンパイラにより実行時にPHPスクリプトをネーティブコードにコンパイルすることで実行速度を高速化する機能がサポートされました。このJIT機能は、OPcacheの一部として実装されており、OPcacheを有効にしてPHPを起動する必要があります。
PHPエクステンションは、組込みおよび共有(shared)の2形態でインストールすることができます。日付(ext/date)、ハッシュ(ext/hash)のような常時利用されるエクステンションは、標準(必須)の組込みエクステンションとしてPHPのコンパイル時に組み込まれ、標準で有効になります。一方、その他の多くのエクステンションは、パッケージマネージャ等で使用環境に合わせて組み込むために、共有モジュールとしてコンパイルされ、必要な時にのみphp.iniのextension命令で指定されて組み込まれます。
PHP 8.5では、OPcacheが標準エクステンションとなり、必須になります。このため、明示的に –enable-opcacheをPHP構築オプション(configure)に指定する必要はなくなり、標準でPHPに組み込まれるようになります。これにより、OPcacheとZendEngineがより密に連携することができるようになり、コードの管理の手間が低減すると共に、将来的な性能向上が期待できます。
パイプ演算子が追加
続いて、おそらくPHP 8.5の新機能の目玉になるであろう「パイプ演算子」を紹介します。パイプ機能では、ある式の結果(出力)を別の式の最初の引数として渡され、シェルスクリプト等ではおなじみの機能です。PHP 8.5で追加されるパイプ演算子は、パイプ機能をスクリプトの中で利用可能にするもので、他のスクリプト言語、例えば、JavaScriptでも提案・実装されています。
では、早速簡単な例をみてみましょう。
<?php
class User {
public function __construct(
public string $username、
public bool $isAdmin = false、
) {}
}function getUsers(): array {
return [
new User(‘root’、 isAdmin: true)、
new User(‘john.doe’、 isAdmin: false)、
];
}function isAdmin(User $user): bool {
return $user->isAdmin;
}
このコードでは、Userというクラスを定義し、2つのプロパティ変数($username、 $isAdmin)を定義しています。getUsers関数は、2つのUserクラスのインスタンスからなる配列を返します。isAdminはUserクラスを引数としてそのユーザが管理者であるか(isAdminがtrueであるか)確認します。
例えば、複数の登録ユーザの中で管理者の数を数えたい場合、従来(PHP 8.4まで)のバージョンでは、以下のように個別の処理を分割して記述する必要がありました。
$users = getUsers();
$admins = array_filter($users、 ‘isAdmin’);
$numberOfAdmins = count($admins);var_dump($numberOfAdmins); // int(1);
先に定義したgetUsers()関数を用いて有効なユーザの定義をUserクラスの配列として取得した後、isAdmin関数をフィルタとしてarray_filter関数に適用し、配列変数$adminsを取得しています。この配列の中で値が真値であるものをcount関数で数えて出力しています。
PHP 8.5でサポートされるパイプ機能では、”|>”により複数の処理を連結し、以下のように簡潔に記述することができます。
$numberOfAdmins = getUsers()
|> fn ($list) => array_filter($list、 isAdmin(…))
|> count(…);var_dump($numberOfAdmins); // int(1);
ここで、isAdmin(…)およびcount(…)において、”…”の部分はFCC(First class callable)構文と呼ばれ、PHP 8.1で追加された機能です。FCCによりコーラブルな関数からクロージャを生成することができます。パイプ演算子を利用することで、一連の処理を1行でシンプルに記述できるようになります。
array_first()、arrai_last()関数追加
PHPでは、v[0]のように配列を添字(インデックス)によりアクセスすることができます。PHPの配列は、添字をキーとするマップとして実装されており、添字に負の値や文字列を指定することも可能です。このため、各要素の値に関して添字の順番と配列におけるメモリ上の位置は異なる場合があります。
ここで、以下のような配列$vを例として見てみましょう。
$v = [1 => ‘a’、 0 => ‘b’、 3 => ‘c’、 2 => ‘d’];
var_dump($v); // [1 => ‘a’、 0 => ‘b’、 3 => ‘c’、 2 => ‘d’]
物理的なメモリ上の配置に基づき、配列の最初(または最後)の要素にアクセスするためには、例えば、PHP 7.3で追加されたarray_key_first() (またはarray_key_last())関数を用いて配列の先頭(または最後)のキーを取得する必要がありました。
var_dump($v[array_key_first($v)]); // string(1) “a”
var_dump($v[array_key_last($v)]); // string(1) “d”
PHP 8.5では、array_first()、array_last()関数が追加され、配列の先頭(最後)の値を簡単に取得できるようになります。
var_dump(array_first($v)); // string(1) “a”
var_dump(array_last($v)); // string(1) “d”
なお、ksort()関数を用いて、配列のキーでソートすることにより、配列における物理的な値の順番は昇順に並び替えられます。
ksort($v); // キーでソート
var_dump($v); // [0 => ‘b’、 1 => ‘a’、 2 => ‘d’、 3 => ‘c’]
var_dump(array_first($v)); // string(1) “b”
var_dump(array_last($v)); // string(1) “c”
var_dump($v[0]); // string(1) “b”
var_dump($v[3]); // string(1) “c”
この場合、array_first()、array_last()関数により取得される配列の先頭(最後)の値は、$v[0] ($v[3])と同じになることがわかります。
今回は、次期マイナーバージョンであるPHP 8.5に関する情報として変更点および追加される機能のいくつかを紹介しました。今回紹介した機能以外にも新たな機能の導入や変更が予定されており、次回以降で紹介する予定です。