Contents
PHP 8.2 の概要と導入の重要性
ポイント
PHP 8.2 は パフォーマンス改善 と 型安全性の強化 を中心に設計されており、既存プロジェクトでも早期の採用が推奨されます。
背景
公式マニュアル migration82(https://www.php.net/manual/ja/migration82.php)では、JIT の内部ロジックが改良されたことやいくつかの内部関数が高速化されたことが記載されています。ただし「約 5 %」という具体的な速度向上は公式には明示されておらず、実際の効果はアプリケーションごとに差があります。
導入メリット
| 項目 | 期待できる効果 |
|---|---|
| JIT 改善・関数最適化 | CPU バウンドな処理で若干のスループット向上(ベンチマーク次第) |
| 型システム拡張 | ランタイムエラーをコンパイル時に検出でき、リグレッションリスクが低減 |
| 新しい組み込み関数・定数 | コードの可読性と安全性が向上 |
PHP 8.2 で追加された主な機能
1. readonly クラス
ポイント
クラス全体に readonly 修飾子を付与でき、インスタンス生成後は すべてのプロパティが不変 になります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
readonly class UserDto { public string $name; public int $age; public function __construct(string $name, int $age) { $this->name = $name; $this->age = $age; } } $dto = new UserDto('Taro', 30); // $dto->age = 31; // Fatal error: Cannot modify readonly property |
効果:不変オブジェクトの実装がシンプルになり、意図しない状態変更を防げます。
2. true 型(リテラル型)
ポイント
文字通り true のみを受け付ける リテラル型 が追加されました。
|
1 2 3 4 5 6 7 |
function enableFeature(true $flag): void { // $flag が false の場合は TypeError になる } enableFeature(true); // OK // enableFeature(false); // Fatal error |
効果:ブール値の意図が明確になり、
falseが渡されるバグをコンパイル時に捕捉できます。
3. Union / Intersection の組み合わせ(DNF 型)
PHP 8.2 では Union (|) と Intersection (&) を自由に組み合わせた型 が正式にサポートされました。これは「分配正規形 (Disjunctive Normal Form, DNF)」と呼ばれ、以下のように記述できます。
|
1 2 3 4 5 6 7 8 9 10 11 |
/** * @param (int|string)&(Countable|ArrayAccess) $value */ function process(mixed $value): void { if ((is_int($value) || is_string($value)) && ($value instanceof Countable || $value instanceof ArrayAccess)) { // $value は count() が安全に呼び出せ、配列アクセスも可能 $value->count(); } } |
ポイント:
(A&B)|(C&D)のような複雑な制約を型システムだけで表現でき、静的解析ツールの精度が向上します。
4. 新しい組み込み関数・定数
| 関数 / 定数 | 説明 |
|---|---|
array_is_list() |
配列が 0 から連続した整数キー のリストか判定 |
fsync() |
ファイルディスクリプタを即時にディスクへ同期 |
json_validate() |
JSON 文字列の構文的妥当性だけをチェック |
str_contains()(既存)・str_ends_with()(既存)等の文字列関数は引き続き利用可 |
注意:
PHP_DEBUG定数は 新規追加 ではなく、コンパイル時に--enable-debugオプションが付与された場合にのみ定義されます。したがって PHP 8.2 固有の変更ではありません。
下位互換性が失われた主な変更点
| 項目 | 変更内容 | 移行時の対策 |
|---|---|---|
| dynamic properties の廃止 | 宣言されていないプロパティへの代入は Error に。 |
必要に応じて #[\AllowDynamicProperties] 属性を付与、もしくはプロパティを明示的に宣言 |
mb_strtolower() の第2引数が必須化 |
エンコーディング指定を省略できなくなった(PHP 8.0 で導入)。 | 常に mb_strtolower($str, 'UTF-8') と記述し、エンコード漏れを防止 |
mysqli_stmt::prepare() の戻り値型変更 |
bool → mysqli_stmt|false に統一。 |
戻り値チェックを if ($stmt === false) { … } に更新 |
curl_multi_select() の返却型が int|false |
失敗時に false が返る可能性が明示化された。 |
=== false 判定でエラーハンドリングを追加 |
実践的な移行手順とベストプラクティス
1. 静的解析ツールで事前チェック
|
1 2 3 |
composer require --dev phpstan/phpstan vendor/bin/phpstan analyse -l max src/ |
- dynamic property の警告 →
#[\AllowDynamicProperties]かプロパティ宣言に修正 - 型ミスマッチ(例:
true型)→ 関数シグネチャと呼び出し側の整合性を確認
2. CI に PHP 8.2 環境を組み込む
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
name: CI on: [push, pull_request] jobs: test-php82: runs-on: ubuntu-latest strategy: matrix: php-version: ['8.2'] steps: - uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} extensions: mbstring, intl - run: composer install --prefer-dist --no-progress --no-suggest - run: vendor/bin/phpunit |
- 本番と同一の拡張モジュール(
mbstring,intlなど)をインストール - テストがすべてパスしたら本番環境へ段階的にロールアウト
3. デプロイフローの更新
| 手順 | 内容 |
|---|---|
| Blue/Green デプロイ | 新バージョン用コンテナを別途起動し、ヘルスチェック後にトラフィック切替 |
| ロールバック | kubectl rollout undo deployment/<app> で直前リビジョンへ復帰 |
| 環境確認 | デプロイ完了後に php -v が 8.2.x を示すことを必ずチェック |
マイグレーションチェックリスト
移行前
- [ ]
composer.jsonの PHP バージョン制約を"^8.2"に変更 - [ ]
phpstan,psalmで dynamic property 警告をすべて解消 - [ ] 新規関数・定数(例:
array_is_list()の使用箇所がないか grep で検索
移行中
| 項目 | 判定基準 |
|---|---|
| Unit Test | 全テストが 100 % パス |
| Integration Test | 外部サービス(DB, API 等)との連携エラーなし |
| Performance Benchmark | 前バージョン比で 同等以上 の実行時間(必要なら JIT 有効化で比較) |
移行後
- [ ] 本番サーバーで
php -vが 8.2 系列を表示していること - [ ] エラーログに
Dynamic property系エラーが出ていないか監視 - [ ] 主要機能のレスポンスタイムが SLA 内に収まっているか測定
よくあるエラーと対処法
| エラー | 原因 | 解決策 |
|---|---|---|
Fatal error: Cannot create dynamic property … |
動的プロパティの使用 | #[\AllowDynamicProperties] を付与、またはプロパティを宣言 |
TypeError: Argument 1 passed to … must be true |
true リテラル型に false が渡された |
呼び出し側ロジックを見直すか、型を bool に緩める |
Undefined constant PHP_DEBUG |
デバッグビルドでない環境で参照した | defined('PHP_DEBUG') && PHP_DEBUG のようにガードする |
まとめ
- 新機能(
readonly class,true型, DNF 型など)は型安全性とコードの可読性を大幅に向上させます。 - 下位互換性が失われた変更点は、特に dynamic properties と mbstring 系関数のシグネチャに注意が必要です。
- 移行手順は「静的解析 → CI でマルチバージョンテスト → Blue/Green デプロイ」のフローを標準化するとリスクが最小化できます。
公式マニュアル(https://www.php.net/manual/ja/migration82.php)と本チェックリストを併用し、段階的にアップグレードすれば、PHP 8.2 の恩恵を安全かつ確実に取り入れることができます。