はじめに
PHP8系(8.0〜8.3)では、言語の表現力・パフォーマンス・型安全性が大きく向上しました。本記事では、実務でとくに役立つ新機能をピックアップしてコード例とともに解説します。
match式:switchをスッキリ書き直す
PHP8.0で追加された match 式は、switch 文の弱点を補う新しい条件分岐構文です。
switchとの主な違い
- 値を返す式として使える
===(厳密比較)でマッチングする- フォールスルー(break忘れ)が起きない
<?php
$status = 2;
// 従来のswitch
switch ($status) {
case 1:
$label = '受付中';
break;
case 2:
$label = '処理中';
break;
default:
$label = '不明';
}
// match式に書き換え
$label = match($status) {
1 => '受付中',
2 => '処理中',
default => '不明',
};
echo $label; // 処理中
複数の値をカンマ区切りでまとめることもできます。
$category = match($status) {
1, 2 => '進行中',
3, 4 => '完了',
default => 'その他',
};
名前付き引数:引数の順番を気にしなくてよくなる
PHP8.0から、関数呼び出し時に引数名を指定して渡せるようになりました。
<?php
// 従来の呼び出し(引数の順番を覚える必要がある)
$arr = array_slice($input, 0, 5, true);
// 名前付き引数(何を渡しているか一目瞭然)
$arr = array_slice(
array: $input,
offset: 0,
length: 5,
preserve_keys: true,
);
とくに省略可能な引数を途中だけ指定したいときに便利です。
// $lengthはデフォルトのまま、preserve_keysだけ指定
$arr = array_slice(array: $input, offset: 0, preserve_keys: true);
Enum:列挙型で定数管理をシンプルに
PHP8.1で導入された enum を使うと、関連する定数をひとつの型にまとめられます。
<?php
// Backed Enum(値あり)
enum OrderStatus: string
{
case Pending = 'pending';
case Processing = 'processing';
case Completed = 'completed';
case Cancelled = 'cancelled';
}
// 使い方
$status = OrderStatus::Processing;
echo $status->value; // processing
// 文字列からEnumへ変換
$fromDb = OrderStatus::from('completed');
echo $fromDb->name; // Completed
Enumにはメソッドを定義することもできます。
enum OrderStatus: string
{
case Pending = 'pending';
case Processing = 'processing';
case Completed = 'completed';
case Cancelled = 'cancelled';
public function label(): string
{
return match($this) {
self::Pending => '受付中',
self::Processing => '処理中',
self::Completed => '完了',
self::Cancelled => 'キャンセル',
};
}
}
echo OrderStatus::Completed->label(); // 完了
従来の const 定数と違い、型として扱えるため関数の引数型ヒントにも使えます。
function updateOrder(int $id, OrderStatus $status): void
{
// $statusはOrderStatus型のみ受け付ける
echo "Order {$id}: {$status->label()}";
}
updateOrder(42, OrderStatus::Completed);
Fibers:軽量な協調的並行処理
PHP8.1で追加された Fiber は、コルーチンのような中断・再開が可能な実行単位です。非同期フレームワーク(RevoltPHPなど)の内部でも活用されています。
<?php
$fiber = new Fiber(function (): void {
echo "Fiber開始\n";
$value = Fiber::suspend('一時停止');
echo "再開。受け取った値: {$value}\n";
});
// Fiberを開始し、最初のsuspendまで実行
$suspended = $fiber->start();
echo "メイン側: {$suspended}\n"; // 一時停止
// 値を渡してFiberを再開
$fiber->resume('こんにちは');
// 出力:
// Fiber開始
// メイン側: 一時停止
// 再開。受け取った値: こんにちは
Fiberは並列処理ではなく協調的な切り替えであることに注意してください。イベントループの実装やストリーム処理に役立ちます。
その他の注目機能まとめ
| バージョン | 機能 | 概要 |
|---|---|---|
| PHP 8.0 | Union型 | int|string のように複数の型を指定 |
| PHP 8.0 | nullsafe演算子 ?-> | nullチェックを連鎖して書ける |
| PHP 8.1 | readonly プロパティ | 一度セットしたら変更不可 |
| PHP 8.2 | readonly クラス | クラス全体をreadonly化 |
| PHP 8.3 | #[Override] 属性 | 親クラスのメソッドを上書きすることを明示 |
// nullsafe演算子の例
$city = $user?->getAddress()?->getCity();
// readonlyプロパティの例
class User {
public function __construct(
public readonly int $id,
public readonly string $name,
) {}
}
$user = new User(1, 'Taro');
// $user->name = 'Jiro'; // エラー!変更不可
まとめ
PHP8系の新機能を活用すると、コードの可読性・安全性・保守性が大きく向上します。
- match式:簡潔な条件分岐
- 名前付き引数:関数呼び出しをわかりやすく
- Enum:定数を型安全に管理
- Fibers:協調的な並行処理の基盤
既存のコードから少しずつ取り入れるだけでも効果が出るので、ぜひ実際のプロジェクトで試してみてください。