PHP 8.1は、2021年11月25日に公開されたPHP 8系のバージョンです。
PHP 8.0で導入されたUnion TypesやAttributes、名前付き引数などの機能をさらに発展させ、型安全性やオブジェクト指向設計を強化する多数の新機能が追加されました。
代表的な新機能には、Enum、readonlyプロパティ、Intersection Types、Fibers、never型、First-class Callable Syntaxなどがあります。
PHP 8.1は現在のPHPにもつながる重要な機能が数多く導入されたバージョンですが、2026年現在はすでに公式サポートが終了しています。
そのため、新規システムでPHP 8.1を採用するのではなく、現在サポートされている、より新しいPHPバージョンを選択することが基本です。
PHP 8.1の主な特徴
型安全性がさらに強化された
PHP 8.1では、プログラム内で扱うデータの種類や状態を明確に表現できる機能が増えました。
代表的なのが、次の機能です。
- Enum
- readonlyプロパティ
- Intersection Types
never型
例えば、従来はユーザーのステータスを文字列で管理することがありました。
$status = 'active';
この方法では、次のようなスペルミスがあっても単なる文字列として扱われます。
$status = 'acitve';
PHP 8.1ではEnumを利用することで、利用可能な値をあらかじめ型として定義できます。
これにより、プログラムの意図をコード上で明確に表現しやすくなっています。
オブジェクト指向プログラミングが扱いやすくなった
PHP 8.1では、readonlyプロパティやfinalクラス定数など、クラス設計をより厳密にする機能も追加されました。
「一度設定した値を変更させたくない」「継承先で定数を書き換えてほしくない」といった設計上のルールを、PHPの言語機能として表現できます。
大規模なWebアプリケーションやライブラリ開発では、こうした機能によって意図しない変更やバグを防ぎやすくなります。
コードを簡潔に記述できる機能が増えた
PHP 8.1ではFirst-class Callable Syntaxや、初期化式でのnewの利用など、従来より短く分かりやすいコードを書ける機能も追加されています。
コード量を減らすこと自体だけでなく、処理の意図を読み取りやすくできる点もメリットです。
PHP 8.1で追加されたEnum
Enumとは
Enumは「Enumeration」の略で、日本語では列挙型と呼ばれます。
あらかじめ決められた候補の中から値を選択するようなデータを、安全に扱うための型です。
例えば、会員ステータスを定義する場合は次のように記述できます。
enum Status
{
case Pending;
case Active;
case Suspended;
}
利用するときは次のように記述します。
$status = Status::Active;
文字列を直接記述する方法とは異なり、定義されていない値を誤って使用するリスクを減らせます。
Backed Enumも利用できる
PHP 8.1のEnumには、値を持たないPure Enumだけでなく、文字列または整数の値を持つBacked Enumがあります。
例えば、次のように記述できます。
enum Status: string
{
case Pending = 'pending';
case Active = 'active';
case Suspended = 'suspended';
}
値を取得する場合はvalueプロパティを利用します。
$status = Status::Active;
echo $status->value;
出力結果は次のようになります。
active
データベースにはactiveなどの文字列を保存し、PHP内部ではStatus::Activeとして扱うといった設計ができます。
PHP 8.1で追加されたreadonlyプロパティ
readonlyプロパティとは
PHP 8.1では、初期化後に再代入できないreadonlyプロパティが追加されました。
例えば、次のように記述します。
class User
{
public readonly int $id;
public function __construct(int $id)
{
$this->id = $id;
}
}
オブジェクトを生成するときに値を設定できます。
$user = new User(100);
echo $user->id;
しかし、初期化後に次のような再代入を行うことはできません。
$user->id = 200;
ユーザーIDや識別子など、オブジェクト生成後に変更させたくない値を扱う場合に便利です。
readonlyは完全な不変性を保証するわけではない
readonlyプロパティを使用したからといって、保持しているオブジェクトの内部状態まで自動的に変更不能になるわけではありません。
そのため、readonlyは基本的に「そのプロパティそのものへの再代入を制限する機能」と考える必要があります。
なお、クラス全体をreadonlyにするreadonly classはPHP 8.1ではなく、PHP 8.2で導入された機能です。
Intersection Typesが追加された
Intersection Typesとは
PHP 8.1ではIntersection Types、つまり交差型が追加されました。
複数の型を同時に満たすことを要求する型指定です。
例えば次のように記述します。
function process(Countable&Iterator $data)
{
}
この場合、$dataはCountableとIteratorの両方を満たしている必要があります。
Union Typesとの違い
PHP 8.0ではUnion Typesが導入されています。
例えば、
function test(A|B $value)
{
}
は、「AまたはB」という意味です。
一方、Intersection Typesでは、
function test(A&B $value)
{
}
となり、「AかつB」という意味になります。
PHP 8.1ではUnion TypesとIntersection Typesを自由に組み合わせることはできません。
両方を組み合わせたDNF型はPHP 8.2から利用できるようになっています。
never型が追加された
never型とは
PHP 8.1では、新しい戻り値型としてneverが追加されました。
neverは、その関数から呼び出し元へ正常に制御が戻らないことを表します。
例えば、必ず例外を投げる関数では次のように利用できます。
function error(string $message): never
{
throw new RuntimeException($message);
}
処理を終了する関数でも利用できます。
function redirect(string $url): never
{
header("Location: {$url}");
exit;
}
voidとneverの違い
voidとneverは似ていますが意味が異なります。
voidは「値を返さない」という意味です。
一方のneverは、「正常な処理として呼び出し元へ制御が戻らない」ことを意味します。
例外を必ず投げる処理やexitによって終了する処理などを、より正確に型として表現できます。
First-class Callable Syntaxが追加された
関数を簡潔にClosureへ変換できる
PHP 8.1ではFirst-class Callable Syntaxが追加されました。
関数やメソッドをClosureとして扱う場合に、...を利用した簡潔な構文を使用できます。
例えば次の関数があるとします。
function double(int $number): int
{
return $number * 2;
}
PHP 8.1では次のようにClosureを取得できます。
$callback = double(...);
そして、
echo $callback(10);
とすると、
20
が出力されます。
オブジェクトのメソッドでも利用できます。
$callback = $object->method(...);
静的メソッドの場合は次のように記述できます。
$callback = MyClass::method(...);
従来のClosure::fromCallable()を利用する方法より、簡潔に表現できる場合があります。
Fibersが追加された
Fibersとは
PHP 8.1ではFibersという実行制御機能が追加されました。
Fibersを利用すると、実行中の処理を一時停止し、その後同じ位置から処理を再開できます。
簡単な例は次のとおりです。
$fiber = new Fiber(function (): void {
echo "処理1\n";
Fiber::suspend();
echo "処理2\n";
});
$fiber->start();
echo "別の処理\n";
$fiber->resume();
実行の流れは次のようになります。
処理1
別の処理
処理2
Fibersは並列処理そのものではない
Fibersについて注意したいのは、使用するだけで自動的に処理が並列化されたり、高速化されたりするわけではないことです。
Fibersは、処理を中断したり再開したりするための低レベルな仕組みです。
そのため、通常のWebサイト制作で直接利用するよりも、非同期処理ライブラリやフレームワークなどの内部実装で利用されるケースがあります。
初期化式でnewを使用できるようになった
コンストラクタのデフォルト値などで利用できる
PHP 8.1では、特定の初期化式でnewを利用できるようになりました。
例えば、コンストラクタのデフォルト引数にオブジェクトを指定できます。
class Service
{
public function __construct(
private Logger $logger = new Logger()
) {
}
}
PHP 8.1では、引数のデフォルト値やstatic変数、グローバル定数、Attributeの引数など、一定の初期化式でオブジェクトを生成できるようになりました。
ただし、どの場所でも自由にnewを使用できるようになったわけではありません。
finalクラス定数が追加された
子クラスによる定数の上書きを防止できる
PHP 8.1では、クラス定数にfinalを指定できるようになりました。
class ParentClass
{
final public const TYPE = 'parent';
}
この定数を子クラスで上書きしようとするとエラーになります。
ライブラリやフレームワークなどで、「継承先でも変更してほしくない定数」を定義するときに役立ちます。
文字列キーを持つ配列を展開できるようになった
配列アンパックの対応範囲が広がった
PHPでは、...を利用して配列を展開できます。
PHP 8.1では文字列キーを持つ配列についてもアンパックできるようになりました。
$array1 = [
'name' => 'Taro',
];
$array2 = [
...$array1,
'age' => 30,
];
結果は次のようになります。
[
'name' => 'Taro',
'age' => 30,
]
同じ文字列キーが複数回登場した場合は、後から指定された値が優先されます。
8進数リテラルに0oを使用できるようになった
8進数であることが分かりやすくなった
従来のPHPでは、8進数を次のように記述していました。
$num = 0777;
PHP 8.1では、次の記述も利用できます。
$num = 0o777;
大文字を使用した次の形式も有効です。
$num = 0O777;
oがoctalを意味するため、コードを見たときに8進数であることを判別しやすくなっています。
array_is_list()が追加された
配列がリスト形式か判定できる
PHP 8.1ではarray_is_list()関数が追加されました。
配列のキーが0から連続した整数になっているかを簡単に判定できます。
$array = ['A', 'B', 'C'];
var_dump(array_is_list($array));
結果は次のようになります。
bool(true)
一方、
$array = [
1 => 'A',
2 => 'B',
3 => 'C',
];
var_dump(array_is_list($array));
の場合は、キーが0から開始していないためfalseになります。
JSON変換などで、配列がリストなのか連想配列なのかを判断したい場合に便利です。
fsync()とfdatasync()が追加された
ファイルの書き込みをストレージへ同期できる
PHP 8.1ではファイル関連の関数としてfsync()とfdatasync()が追加されました。
例えばfsync()は次のように利用できます。
$file = fopen('data.txt', 'w');
fwrite($file, 'Hello');
fsync($file);
fclose($file);
fsync()はファイルのデータや必要なメタデータをストレージへ同期するために利用します。
fdatasync()もデータをストレージへ同期する関数ですが、基本的にはファイルデータを中心に同期する点が異なります。
単なるfflush()とは役割が完全に同じではありません。
PHP 8.1で変更された主な仕様
組み込み関数へnullを渡す処理が非推奨になった
PHP 8.1では、組み込み関数の非nullableなスカラー型引数へnullを渡す処理が非推奨になりました。
例えば次のようなコードです。
strlen(null);
従来は暗黙的な型変換によって動作する場合がありましたが、PHP 8.1では注意が必要です。
値がnullになる可能性がある場合は、次のように明示的に処理する方法があります。
$value = null;
echo strlen($value ?? '');
PHP 8.1以降では、こうした暗黙的な型変換に依存しないコードを書くことが重要です。
floatからintへの精度を失う暗黙変換が非推奨になった
PHP 8.1では、小数部分などが失われるfloatからintへの暗黙変換が非推奨になりました。
例えば次のコードです。
$array = [];
$array[15.5] = 'test';
15.5を整数に変換すると小数部分が失われるため、非推奨警告の対象になります。
一方、
$array[15.0] = 'test';
のように値を失わず整数へ変換できるケースとは扱いが異なります。
内部クラスやインターフェースの戻り値型に注意が必要になった
PHP 8.1では、多くの内部クラスやインターフェースのメソッドについて戻り値型が明確になっています。
そのため、IteratorなどPHP標準のインターフェースを実装している既存クラスでは、戻り値型に関する非推奨警告が発生する場合があります。
互換性上すぐに適切な戻り値型を追加できない場合は、移行用としてReturnTypeWillChange属性を利用できます。
#[\ReturnTypeWillChange]
public function current()
{
// 処理
}
ただし、これは恒久的な対応というより、古いコードを移行するための一時的な手段として考えるのが適切です。
Serializableの利用に注意が必要になった
PHP 8.1では、従来のSerializableインターフェースに関連する処理について非推奨化が進みました。
Serializableを実装しているにもかかわらず、__serialize()と__unserialize()を実装していないクラスでは非推奨警告が発生する場合があります。
古いPHP向けに作成されたライブラリや独自クラスをPHP 8.1へ移行するときには確認が必要です。
MySQLiのエラー処理が変更された
デフォルトのエラー報告モードが変更された
PHP 8.1では、MySQLiのデフォルトのエラー報告モードが従来より厳格になりました。
以前は失敗時にfalseが返され、その戻り値を確認する形で処理していたコードでも、PHP 8.1ではmysqli_sql_exceptionなどの例外が発生する場合があります。
そのため、PHP 8.0以前からPHP 8.1以上へ移行する場合は、データベース処理の例外処理を確認することが重要です。
以前と同じようにエラー報告を抑制したい場合は、
mysqli_report(MYSQLI_REPORT_OFF);
を利用できます。
ただし、新しいコードでは例外を適切に処理する設計を検討したほうがよいでしょう。
$GLOBALSの扱いにも変更が加えられた
$GLOBALS配列全体に対する操作が制限された
PHP 8.1では、$GLOBALSの扱いにも変更があります。
例えば、
$GLOBALS['name'] = 'Taro';
のように個別の要素を読み書きすることは可能です。
一方で、$GLOBALS配列そのものを丸ごと書き換えるような処理には制限があります。
古いPHPコードで特殊なグローバル変数操作を行っている場合は、PHP 8.1への移行時に確認が必要です。
PHP 8.0とPHP 8.1の違い
PHP 8.1では新しい言語機能が多数追加された
PHP 8.0とPHP 8.1の代表的な違いを整理すると、次のようになります。
| 機能 | PHP 8.0 | PHP 8.1 |
|---|---|---|
| Enum | 非対応 | 対応 |
| readonlyプロパティ | 非対応 | 対応 |
| Fibers | 非対応 | 対応 |
| Intersection Types | 非対応 | 対応 |
| First-class Callable Syntax | 非対応 | 対応 |
never型 | 非対応 | 対応 |
| finalクラス定数 | 非対応 | 対応 |
| 文字列キーの配列アンパック | 非対応 | 対応 |
array_is_list() | 非対応 | 対応 |
fsync() | 非対応 | 対応 |
0oによる8進数表記 | 非対応 | 対応 |
PHP 8.1はPHP 8.0を全面的に作り直したバージョンというより、PHP 8.0で進んだ型安全性やモダンな言語設計をさらに発展させたバージョンと考えると分かりやすいでしょう。
PHP 8.1を利用するメリット
不正な値を扱うリスクを減らせる
Enumや型宣言を活用することで、システム内で許可されていない値を誤って利用するリスクを減らせます。
例えば、
$status = 'active';
という単なる文字列ではなく、
$status = Status::Active;
として扱えるため、コード上で値の意味が分かりやすくなります。
設計上のルールをコードに反映できる
readonlyプロパティを利用すれば、一度設定したあと変更してはいけない値をコード上で表現できます。
public readonly int $id;
このような記述を見るだけで、そのプロパティが初期化後に再代入されない設計であることが分かります。
保守性を高めやすい
EnumやIntersection Types、readonlyなどを利用すると、コードの制約や意図が明確になります。
複数人で開発する場合や長期間運用するシステムでは、こうした言語機能がコードの読みやすさや保守性の向上につながります。
PHP 8.1へ移行するときの注意点
既存コードの互換性を確認する
PHP 7.xやPHP 8.0からPHP 8.1へ移行する場合は、新機能を利用することだけでなく、既存コードが正しく動作するか確認する必要があります。
特に確認したい項目は次のとおりです。
- 組み込み関数へ
nullを渡していないか - floatからintへの暗黙変換がないか
- PHP標準インターフェースを実装しているクラスの戻り値型
- 古い
Serializable実装を使用していないか - MySQLiの例外処理に問題がないか
$GLOBALSへ特殊な操作を行っていないか- Composerパッケージが対応しているか
- PHP拡張モジュールが対応しているか
- 使用しているCMSやフレームワークが対応しているか
PHP本体だけを更新しても、周辺ライブラリが対応していなければ正常に動作しない場合があります。
本番環境へ導入する前にテストする
PHPのバージョンアップでは、開発環境やステージング環境で十分なテストを行うことが重要です。
特に、ログイン、フォーム送信、データベース更新、メール送信、ファイル操作、外部API通信など、システムの主要機能を確認しておく必要があります。
エラーログや非推奨警告もチェックすると、将来的に問題となるコードを発見しやすくなります。
2026年現在PHP 8.1を使うべきか
PHP 8.1はすでに公式サポートが終了している
PHP 8.1はPHPの進化において重要なバージョンですが、2026年現在はすでにPHP公式のサポートが終了しています。
そのため、新規Webサイトや新しいWebアプリケーションでPHP 8.1を採用することは基本的に推奨されません。
現在公式サポートの対象となっている、より新しいPHPバージョンを利用するのが適切です。
PHP 8.1を利用している既存システムは移行を検討する
既存システムがPHP 8.1で稼働している場合、直ちにシステムが動かなくなるわけではありません。
しかし、公式のセキュリティアップデートが提供されなくなるため、長期間そのまま利用することにはセキュリティ上のリスクがあります。
使用しているCMS、フレームワーク、Composerパッケージ、PHP拡張などの対応状況を確認しながら、現在サポートされているPHPバージョンへの移行を進めることが重要です。
PHP 8.1はPHPの型安全性を大きく高めたバージョン
Enumやreadonlyなど現在につながる重要機能が追加された
PHP 8.1では、Enum、readonlyプロパティ、Intersection Types、never型、First-class Callable Syntax、Fibersなど、多数の重要な機能が追加されました。
特にEnumによって決められた候補を型として扱えるようになったことや、readonlyプロパティによって初期化後に変更させたくない値を表現できるようになったことは、PHPのオブジェクト指向設計や型安全性を向上させる大きな変更です。
バージョンアップ時は非互換変更にも注意する
PHP 8.1には新機能だけでなく、既存コードへ影響する変更も含まれています。
組み込み関数へのnullの受け渡し、floatからintへの暗黙変換、標準インターフェースの戻り値型、MySQLiのエラー処理などは、古いPHPから移行するときに特に注意したいポイントです。
PHP 8.1の機能を理解する際は、新しく追加された機能だけを見るのではなく、既存コードへの影響や後方互換性の変更も合わせて理解しておくことが重要です。
以上、PHP 8.1の特徴や新機能、主な変更点についてでした。
最後までお読みいただき、ありがとうございました。










