秋といえば、WordPressを動かすサーバーサイドスクリプト言語、PHPの新バージョンがリリースされる時期です。11月21日のバージョン8.4のGA版リリース(一般提供)に向けて、PHP開発チームは8月の機能凍結以来、リリース候補を含む新たなコードベースの初期バージョンを多数発表しています。
新機能、改善点、非推奨機能に加えて、2024年のこの時期には、PHPのリリースサイクルに調整が加えられます。現在サポートされているすべてのバージョンのセキュリティリリースの終了は、PHPのGA版リリース時ではなく年末に同期されることになりそうです。
また、PHP 8.4のサポートは1年延長されるため、2028年まで安全に使うことができます(2年間はセキュリティとバグ修正、2年間はセキュリティ修正のみ)。
今回は、PHP 8.4の新機能についてご紹介します。
PHP 8.4の新機能と改善点
昨年リリースされたPHP 8.3の新機能は、今回の8.4で導入された一部機能と比較すると、控えめに感じるかもしれません。
PHP 8.4で追加された新機能は以下のとおりです。
プロパティフック
プロパティフックは、PHPのオブジェクト指向プログラミング(OOP)における、「ゲッター(getter)」と「セッター(setter)」の扱いに全く新しいアプローチを導入し、クラスファイルの構造を単純化することを可能にします。
プロパティフックで置き換えられるものの例として、以下のような$size
と$flavor
があります。これらのプロパティは、外部から直接アクセスされないようにするため、private
として設定されています。このため、publicであるgetterメソッドとsetterメソッドがプロパティへのアクセスを仲介します。
class Coffee
{
private string $size;
private string $flavor;
public function __construct(string $size, string $flavor) {
$this->size = $size;
$this->flavor = $flavor;
}
// コーヒーのサイズと風味を設定(セット)
public function setSize(string $size): void {
$this->size = $size;
}
public function setFlavor(string $flavor): void {
$this->flavor = $flavor;
}
// コーヒーのサイズと風味を取得(ゲット)
public function getSize(): string {
return $this->size;
}
public function getFlavor(): string {
return $this->flavor;
}
} // クラス終了
// コーヒーを淹れる
$coffee = new Coffee('スモール', 'パンプキンスパイス');
print $coffee->getSize() . ' ' . $coffee->getFlavor(); // 「スモール・パンプキンスパイス」を出力
// 注文を変更
$coffee->setSize('グランデ');
$coffee->setFlavor('モカ');
print $coffee->getSize() . ' ' . $coffee->getFlavor(); // 「グランデ・モカ」を出力
あるいは、クラスに多くのプロパティがあり、getterメソッドやsetterメソッドを多数書く代わりに、マジックメソッドの_get
や_set
を使用するかもしれません。以下のように、やや乱雑なswitch
文で整理することもできます。
// __setマジックメソッドの例
public function __set(string $key, $value): void
switch ($key) {
case 'size':
$this->size = $value;
break;
case 'flavor':
$this->flavor = $value;
break;
default:
throw new InvalidArgumentException('無効な入力です');
}
}
// 後でコーヒーの順番をこのように変更できる
$coffee->size = 'グランデ';
$coffee->flavor = 'モカ';
どのような方法をとるにせよ、クラス内のプロパティの数が多ければ多いほど、 それらを操作するコードは、クラスファイルの先頭付近の定義から遠ざかることになります。さらに、_get
と_set
マジックメソッドの実装によっては、公開する予定のなかったオブジェクトのprivateプロパティやprotectedプロパティへのアクセスを提供してしまうことがあります。
新たに導入されるプロパティフックは、ゲッターとセッターの機能をプロパティ自体に組み込みます。以下の例では、Coffeeクラスの$size
プロパティと$flavor
プロパティがpublicになっていますが、set
フックには基本的なバリデーション(チェック機能)が追加され、直接の代入とは区別されています。
// Coffeeクラスのトップにあるプロパティ定義
class Coffee
{
public string $flavor {
set(string $value) {
if (strlen($value) > 16) throw new InvalidArgumentException('入力が長すぎます');
$this->flavor = $value;
}
}
public string $size {
set(string $value) {
if (! in_array($value, array(‘スモール’, ‘グランデ’))) throw new InvalidArgumentException('有効なサイズではありません');
$this->size = $value;
}
}
// 残りのCoffeeクラス
}
// コーヒーを定義
$coffee = new Coffee();
$coffee->size = 'グランデ';
$coffee->flavor = 'パンプキンスパイス';
同様に、get
フックを使用することで、一見ただのプロパティ参照に見えるものにも機能を追加することができます。
// 簡易のCoffeeクラス
class Coffee
{
public string $flavor {
get {
return $this->flavor . 'スパイス';
}
}
}
// 風味を作成
$coffee = new Coffee();
$coffee->flavor = 'パンプキン'; // 値 「パンプキン」を保存
print $coffee->flavor; // 「パンプキンスパイス」を出力
PHPのマジックメソッドとは異なり、プロパティフックはインターフェースや抽象クラスで使用することができます。以下はインターフェースの例です。
interface Coffee
{
public string $size { get; set; }
public string $flavor { get; set; }
}
非対称な可視性
先ほどの一般に公開されているgetterメソッドやsetterメソッドは、クラス内のprivateプロパティやprotectedプロパティにアクセスするための従来のアプローチです。
PHP 8.4の便利な機能として、アクセスされるコンテキストによって、プロパティの可視性のレベルを変更することができます。つまり、あるプロパティが読み込まれるときにはpublicでも、設定時にはprivateまたはprotectedになるということです。
例を見てみましょう。
class Coffee
{
public private(set) string $flavor = 'パンプキンスパイス';
}
$coffee = new Coffee();
print $coffee->flavor; // 「パンプキンスパイス」を出力
$coffee->flavor = 'モカ'; // エラー(可視性)
この例では、クラスの$flavor
プロパティは、設定コンテキスト以外ではpublicです。すでにかなりシンプルですが、非対称の可視性にはさらに便利な方法があります。
class Coffee
{
// コンテキストが設定されていない場合はpublicを想定
private(set) string $flavor = 'パンプキンスパイス';
}
プロパティフックと非対称の可視性を組み合わせて使うことで、さまざまな可視性のオブジェクトプロパティをかなり柔軟に扱うことができます。
括弧なしのnew
連結
短縮形といえば、これまでnew
や連鎖メソッドを呼び出すには以下のように括弧でくくる必要がありました。
$coffee = (new Coffee())->getFlavor()->getSize();
PHP8.4では、括弧でくくる必要がなくなります。
$coffee = new Coffee()->getFlavor()->getSize();
些細な変更に思えますが、このちょっとした括弧を削除するだけで可読性が上がり、デバッグしやすくなります。
配列の項目を探すための新関数
すでに存在していたように感じるかもしれませんが、PHP 8.4ではarray_find()
という関数が導入されます。これはコールバック関数で指定された条件に一致するメンバ関数を配列要素から探すことができます。
この関数は、コールバック関数のテストに一致する最初の要素の値を返します。
array_find_key()
:array_find()
と同様だが、戻り値は要素そのものの値ではなく一致した要素のキーarray_all()
:テストする配列のすべての要素がコールバックのテストに一致する場合はtrue
array_any()
:配列の要素の少なくとも1つがコールバックのテストに一致する場合はtrue
最後の2つの関数は、配列のキーや内容の代わりに真偽値を返すことに注意してください。
簡単な例を見てみましょう。
$array = [
'a' => 'モカ',
'b' => 'キャラメル',
'c' => 'メープル',
'd' => 'パンプキン'
];
// 5文字の最初のフレーバー名を探す
var_dump(array_find($array, function (string $value) {
return strlen($value) == 5;
})); // 「キャラメル」を返す(「パンプキン」も同じ長さだが)
// 5文字以上の名前を持つ最初のフレーバーの配列キーを探す
var_dump(array_find_key($array, function (string $value) {
return strlen($value) > 5;
})); // 「b」を返す
// フレーバー名の長さが5文字以下かどうかをチェック
var_dump(array_any($array, function (string $value) {
return strlen($value) < 5;
})); // trueを返す
// すべてのフレーバー名が8文字より短いかチェック
var_dump(array_all($array, function (string $value) {
return strlen($value) < 8;
})); // trueを返す
HTML5のパース
HTML5は、現代のウェブページの構造における事実上の標準ですが、PHPのドキュメントオブジェクトモデル(DOM)解析技術は、HTML 4.01でHTML 4.01で停滞していました。
PHP 8.4では、古いHTML標準で動作する既存のDOMDocument
クラスをアップグレードするのではなく、 HTML5に対応したDomHTMLDocument
クラスが新たに導入されています。
以下のように、HTML5ページの内容をインポートすることができます。
$document = DomHTMLDocument::createFromString($html)
上記のcreateFromString($html)
コンストラクタに加えて、createFromFile($path)
とcreateEmpty()
もサポートしています。
パーサーは、main
、article
、section
のようなセマンティックなHTML5タグを認識します。
マルチバイトのtrim関数
また、多くのユーザーが待望していた機能として、trim関数におけるマルチバイトのサポートがあります。
mb_trim()
mb_ltrim()
mb_rtrim()
長年使用されているtrim()
関数と同様、mb_trim
はマルチバイト文字を含む文字列の両端から、空白文字や改行文字などの特殊文字を取り除きます。他の関数は、文字列の左端か右端のどちらかを切り取ります。
PHP 8.4の非推奨機能
PHPの各リリースには、最終的にプラットフォームから削除される可能性のある機能や関数(中にはかなり曖昧なものも)が多数含まれています。PHP 8.4で非推奨となる機能の一つに、Cookieレスセッション追跡があります。
GET/POSTセッション
一般に、ユーザーセッションの追跡にはCookieの使用が推奨されますが、PHPではセッションIDのデータをGETやPOSTパラメーターに固定することもサポートされていました。URL のパラメータによるセッション追跡を有効にするには、 PHPの設定session.use_only_cookies
を無効にし、session.use_trans_sid
設定を有効にします。
PHP 8.4では、これらの設定のいずれの状態でも非推奨の警告が表示され、 ウェブサイトのログに表示される可能性があります。PHP 9のリリース時には使用できなくなります。
その他の非推奨(および削除済み)機能
最後に、PHP 8.4の開発チームが非推奨とした機能一覧をご紹介します。
- 段階的非推奨であった
DOMDocument
およびDOMEntity
プロパティが正式に非推奨に DOMImplementation::getFeature($feature, $version)
(削除)DOM_PHP_ERR
定数unserialize()
で使用される「S」タグsession.sid_length
およびsession.sid_bits_per_character
SplFixedArray::__wakeup()
の非推奨xml_set_object()
およびxml_set_*_handler()
の文字列メソッド名dba_key_split()
にnullとfalseを渡す- ext/hash関数にオプションとして不正なデータ型を渡す
- 定数
SUNFUNCS_RET_STRING
、SUNFUNCS_RET_DOUBLE
、SUNFUNCS_RET_TIMESTAMP
- 独自のCSVエスケープメカニズム
E_STRICT
定数strtok()
定数- ユーザーレベルの出力ハンドラから文字列以外の値を返す
- ユーザーレベルの出力ハンドラでの出力の生成
file_put_contents()
で$data
を配列として使用するmysqli_ping()
およびmysqli::ping()
mysqli_refresh()
mysqli_kill()
mysqli_store_result()
の2番目のパラメータlcg_value()
uniqid()
md5()
、sha1()
、md5_file()
、sha1_file()
trigger_error()
にE_USER_ERROR
を渡す- アンダースコア(_)をクラス名として使用する
SOAP_FUNCTIONS_ALL
定数、およびこの定数をSoapServer::addFunction()
に渡す
まとめ
PHP 8.4には、注目したい変更点がいくつか含まれています。Kinstaでは、この最新バージョンを自社のサーバーに導入し、毎年恒例のPHPベンチマーク、PHPベースのコンテンツ管理システム(CMS)でのテストを実施する予定です。
また、開発者の皆さんがPHP 8.4の新機能、特にプロパティフックをいつプロジェクトに取り入れるのかも気になるところです。
コメントを残す