PHP重鎮の廣川類氏によるコラム「PHPの最新状況:PHP 8.1の開発がいよいよ最終段階に(第19回)」

PHP

廣川類

PHP 8.1の開発が順調に進行中で、正式版は11月25日にリリース予定です。今回はその主な新機能を紹介します。まず、「交差型(Intersection)」の導入で、関数やメソッドの引数、戻り値に複数の型に共通する要素を指定できるようになります。次に、「never型」の導入で、処理が戻らない関数の明示的な指定が可能になります。さらに、「readonly型」の導入により、初期化後に変更ができない変数を作成できます。また、「...」による配列展開で、連想配列の要素を簡単に展開できるようになりました。最後に、「...」構文によるクロージャで、より簡便にクロージャを定義できます。次回は、更なる新機能と下位互換性がない変更点を紹介予定です。

夏もそろそろ終わる頃となりましたが,次期マイナーバージョンアップとなるPHPバージョン8.1の開発は計画通り順調に進んでおり,7月20日にフィーチャーフリーズされた後,ベータ版がリリースされています.本稿では,前回に引き続きPHP 8.1における変更点について紹介します.

PHP 8.1の開発スケジュール

PHP 8.1の開発では,7月20にフィーチャーフリーズが行われた後,7~8月にベータ版,9~11月にリリース候補版のリリースが予定されてています.本稿執筆時点では,ベータ版の最終版であるβ3版が最新となっています.開発が順調にいくと,正式版が11月25日にリリースされる予定です.

本稿では,PHP 8.1で追加される機能を引き続き紹介します.

交差型の導入

 PHP 8.0では合併型(Union)が導入されました.PHP 8.1では交差型(Intersection)が導入されます.Unionでは,関数・メソッドの引数または戻り値に複数の型の候補を指定できます.複数の型は論理和と同様に’|’で挟んで指定します.一方,Intersectionは論理積に相当し,複数の型に共通する要素を’&’で挟んで指定します.簡単な例を見てみましょう.

<?php

class Test {

  private Traversable&Countable $ci;

  public function setIterator(Traversable&Countable $c) {

     $this->ci = c;

  }

  public function getIterator(): Traversable&Countable {

     return $this->ci;

  }

}

この例では,TestクラスのsetIteratorメソッドの引数の型,getIteratorメソッドの戻り値およびプライベート変数$ciの型として,Traversable & Countable を指定しています.これは,TraversableかつCountableであることを指定しており,どちらか片方のクラス型(またはインターフェイス)のみ有する場合はエラーとなります.複数のインターフェイスを指定するケースなどでの利用が想定されます.

never型

PHP 8.1では,関数から処理を戻さないことを明示的に指定する戻り値型として never が導入されます.これは,例えば,HTTPヘッダの出力でリダイレクト指定を行った後,PHPスクリプトの処理を終了するケースが想定されます.以下にリダイレクト処理を行う関数の例を示します.

<?php

function redirect(string $uri): never {

 header(‘Location:’.$uri);

  exit();

}

戻り値型として”never”を指定し,この関数から処理が戻らないことを明示的に指定しています.後日,例えば,3行目のようなコードを追加してしまったとしましょう.

<?php

function redirect(string $uri): never {

    if ($uri===”) {return;}

    header(‘Location:’.$uri);

    exit();

}

–-

この場合,neverの指定により処理が戻ることが禁止されているため,3行目でreturnを実行するコードはエラーを発生します.このようにneverを指定することで,処理が戻らない関数の処理を明示的に指定することができるようになります.

 

readonly型

 PHP 8.1ではreadonly指定子を付与することにより初期化後に変更ができない変数を作成できるようになります.この動作は,定数に似ていますが,初期化される値が固定値でなくて良いという特徴があります.以下の例を見てみましょう.

<?php

class Test {

  public readonly string $prop;

  public function __construct(string $v){

    $this->prop=$v;     

  }

}

この例では,プロパティ変数$propにreadonlyが指定されています.コンストラクタでこの変数に初期値が代入されています.以下のように”foo”を指定してオブジェクトを作成することにより,readonlyを指定したプロパティ変数$propにその値が代入されます.しかし,3行目でプロパティ変数に値を代入しようとすると,初期化時ではないため,エラーを発生します.

$obj = new Test(“foo”);

var_dump($obj->prop);  // “foo”

$obj->prop=”boo”;         // エラー発生

‘…’による配列展開

 PHP 8.1では’…’により連想配列における配列展開が可能となりました.この’…’というキーワードはいくつかの使用法が既に定義されていますので,順番に説明します.

 まず,PHP 5.6において関数(メソッド)の引数において配列のよそを展開する演算子として’…’が導入されています.以下の例において,test関数の引数として複数の配列($a, $b)を指定しています.’…’を配列変数の前に付与することにより,当該配列の要素が展開されます.この例では,test(1,2,3) のように指定されます.

function test({ var_dump(func_get_args());}

$a=[1,2];

$b=[3];

test(…$a,…$b); // [1,2,3]

 次に PHP 7.4 において添字配列における配列の展開にもこの’…’が利用可能となりました.以下の例では,配列変数$a, $b を別の配列変数に代入する際に’…’ を指定することで,配列の要素を展開しています.

$a=[1,2];

$b=[3];

$c=[0,…$a,…$b];

var_dump($c);   // [0,1,2,3]

 PHP 8.1では,添字配列に加えて,連想配列においても’…’を指定できるようになります.以下の例では,連想配列$a,$bを連想配列$cに代入しています.

$a=[“a”=>1];

$b=[“b”=>2];

$c=[“a”=>0,…$a,…$b];

var_dump($c);   // “a”=>1, “b”=>2

連想配列$cに指定される値は,[“a”=>0,”a”=>1,”b”=>2] となります.なお,連想配列のキーが重なる場合,最後(より右側)に指定された要素の値が採用されます.この例では,”a”をキーとする値について,0と1が指定されていますが,後で指定された1が採用されています.

‘…’構文によるクロージャ

 PHP 7.1では,コール可能(callable)な関数(メソッド)を用いてクロージャを定義する仕組みが定義されています.fromCallable というスタティックオブジェクトを定義することで,クロージャを定義できます.

public static Closure::fromCallable(callable $callback) : Closure

 例えば,組込み関数strlenを用いてクロージャを定義すると以下のようになります.

$fn = Closure::fromCallable(‘strlen’);

 PHP 8.1では更に便利になり,以下のように’…’ を引数に指定するだけでクロージャを定義することができます.

$fn = strlen(…);

 今回も引き続きPHP 8.1の新機能を紹介しました.次回は,導入される機能の続きと下位互換性がない変更点などについて紹介します.

 

<< PHPの最新状況:PHP 8.1の開発が進む(第18回)PHPの重鎮廣川類氏のコラム「PHPの最新状況:PHP 8.1で導入される新機能(第20回)」 >>

関連記事

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

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

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

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

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