thumbnail

【PHP8.x】PHP8.1の新機能!PHP7との違いまとめ

PHP8.1がリリースされました。PHP7からできることが非常に増えており、PHPがますます便利になっています。
この記事ではPHP7とPHP8.xの違いを、主要な新機能についてまとめてました。深堀りすべき内容は別記事として分離します。なお、PHP7からPHP8へのバージョンアップの方法はこちらをご覧ください

列挙型(enum)の追加

他の言語でお馴染みの列挙型が使えるようになりました。

//列挙型
enum Color
{
  case Red;
  case Green;
}

//引数をColor型に限定できる
function printColor(Color $color)
{
  // 
}

//列挙型へのアクセス
$color = Color::Red;//::でアクセス
printColor($color);

PHPの列挙型は、他にもメソッドを持てたりインターフェースやトレイトが利用できたりと、非常に多機能です。
PHPの列挙型については別記事で詳しく説明しています。

read onlyプロパティの追加

read onlyを指定すると読み取り専用のプロパティが作れます。

<?php 
class Person
{
  public function __construct(
    public readonly string $name, //読み取り専用
    public int $age //普通のプロパティ
    ){}
}

$person = new Person('Taro', 30);
$person->age = 10; //OK
//$person->name = "Jiro"; エラーが出る

このコンストラクタの記述方法をご存じない方は、コンストラクタの省略記法(ページ内リンク)を参照下さい。

First-class callable syntax

関数からクロージャに変換する際の新しい記述方法です。
簡単に言うと、関数を別名に保存してから別名で呼び出すための手段です。
従来Closure::fromCallable()として呼び出していたものを簡単に記述できるようになります。

//$fn = Closure::fromCallable('strlen'); 従来
$fn = strlen(...);
echo $fn('hoge'); //4

$fn2 = count(...);
echo $fn2([1, 2, 3, 4, 5]); //5

デフォルトパラメータでnewできる

関数やコンストラクタのデフォルトパラメータで、newを用いたインスタンスの作成ができます。

function hoge(Person $person = new Person('Jiro', 3))
{
  echo "{$person->name}({$person->age})";
}

hoge(new Person('Taro', 5)); // Taro(5)
hoge(); //Jiro(3)

新しい型のサポート

交差型(&)

交差型をサポートしました。型Aと型Bがあるとき、交差型A&BはAかつBの型を表現します。

//IteratorかつCountable
function count_and_iterable(Iterator&Countable $value)
{
  //
}

never型

関数の戻り値にnever型が追加されました。例外のスローやexit、dieなど、関数が決して値を返さないときに宣言します。

Union型[8.0]

AまたはBの型を表現します。

class MyClass {
  //intまたはfloat
  private int|float $number;

  //
}

mixed型[8.0]

任意の型はmixedで表現します。

クラス定数のfinal宣言

クラス定数をfinal宣言することができるようになり、オーバーライドを禁止できるようになりました。

class MyClass1 
{
  final public const HOGE = "HOGE";
}

class MyClass2 extends MyClass1
{
  // public const HOGE = "FUGA"; //エラー
}

Fibers

Fiberを使うと非同期処理を綺麗に表現することが出来ます。
Fiberについて詳しく説明すると1記事では足りないので、別記事で紹介予定です。

文字列がキーの連想配列のアンパック

文字列がキーの連想配列のアンパックもサポートされました。

$ary1 = ['hoge' => 1];
$ary2 = ['fuga' => 2];
$ary3 = ['hoge' => 10, ...$ary1, ...$ary2]; //[hoge] => 1 [fuga] => 2

属性・アトリビュート[8.0]

アトリビュートともいいます。コードのロジックとは別にメタデータを埋め込める機能です。
アトリビュートに関してもこの記事では足りないので別記事で紹介します。

match式[8.0]

match式が導入されました。値を返すswitch文のようなものです。

$arg = 'B';

//switch式
switch ($arg)
{
  case 'A':
    echo 'Apple';
    break;
  case 'B':
    echo 'Banana';
    break;
  default:
    echo 'hoge';
    break;
}

//上のswitch式と等価なmatch式
$result = match($arg)
{
  'A' => 'Apple',
  'B' => 'Banana',
  default => 'hoge'
};

echo $result;

matchはswtichを置き換えるものではなく、重要な相違点がいくつかあります。

switchとmatchの違い

  1. 比較は厳密等価演算
  2. break文が不要
  3. =>の右側は1つの式

①比較は厳密等価演算

switch文は式と値が等価演算(==)で比較されていましたが、match式では厳密等価演算(===)で評価されます。

②break文が不要

break文はいりません。フォールスルーしたい場合は、=>の左辺にカンマ区切りで複数の値を指定します。

③=>の右側は一つの式

=>の右側に複数の式を書きたい場合はswitch式を利用します。

コンストラクタの省略記法[8.0]

コンストラクタの省略記法が導入されました。

//新しい記法
class Person
{
  public function __construct(
    public string $name, 
    public int $age 
    ){}
}

//従来の記法
class Person
{
  public string $name;
  public int $age;
  
  public function __construct(string $name, int $age)
  {
    $this->name = $name;
    $this->age = $age;
  }
}

Nullsafe演算子[8.0]

nullチェックのif文を一々記述する代わりに、nullsafe演算子を用いて一気にメソッドチェーンができます。

従来ならnullチェックをしていたオブジェクトからメソッドチェーンするとき、アロー演算子の前に?をつけます。
hoge?->fugaのような記述になります。

//従来
if ($numA !== null) {
  $numB = $numA->B;

  if ($numB !== null) {
    $numC = $numB->C();
 
    if ($numC !== null) {
      $numD = $numC->D;
    }

    if ($numD !== null) {
      $numE = $numD->E;
    }
  }
}

//nullsafe演算子
$numE = $numA?->B?->C()?->D->E;

メソッドチェーンの途中でnullがあった場合は全体がnullとして評価されます。

名前付き引数[8.0]

関数を呼び出す際、呼び出し側で引数名を明示できるようになりました。

function printPerson($name="Taro", $age=10, $blood="C")
{
  echo "{$name}({$age}:{$blood})";
}

printPerson(name: 'Jaro', blood: 'C');

これによって、オプション引数のスキップや引数の順序を気にせずに関数の呼び出しができます。

その他

・PHP8からJIT機能を搭載。JITエンジンを有効にすれば実行効率が向上

・@演算子が致命的なエラーを隠さないようになった

・等価演算(==)の判定方法の変更。より直感的に。

まとめ

以上、PHP8.x系の新機能について、概要をさらいました。
他の言語にある機能を搭載しつつも、PHP独自の進化も見受けられます。
深堀りできなかった内容については別記事でまとめる予定です。

参考

PHP8.1 Released! (公式ドキュメント)

https://www.php.net/releases/8.1/en.php