エラーや例外に関する機能強化
続けて、一部の拡張機能におけるエラーや例外のハンドリングに関する機能強化について紹介します。
SQLiteにおける例外発生のデフォルト化
PHP 8.3以降から、SQLite3拡張モジュールにおける例外発生の設定が変化していきます。PDOなどではすでにデフォルトで例外を発生するようになっているので、これに合わせる形になります。PHP 8.3ではSQLite3Exceptionが新設され、表のように例外の発生について変更されていきます。ちなみにenableExceptionsメソッドは、例外の発生の有無を引数(既定値はfalse)で設定し、直前の状態を返します。
バージョン | 既定でのenableExceptions()の戻り値 | enableExceptions(false)の結果 |
---|---|---|
8.2 | false(例外発生なし) | 実行可(例外なしに戻せる) |
8.3 | false、E_DEPRECATED発生(例外発生なし) | E_DEPRECATED発生(例外なしに戻せる) |
9 | true(例外発生あり) | エラー(例外なしに戻せない)、E_DEPRECATED発生(引数をtrueにした場合) |
10 | メソッド未定義のエラー | メソッド未定義のエラー |
このように、PHP 8.3では例外のあり/なしを使い分けることができますが、将来的には例外なしの状態に戻せなくなり、最終的にはenableExceptionsメソッドそのものも廃止されます。
PHP 8.3のみで関数の呼び出し結果を見てみると、以下のようになります。enableExceptions(true)によって例外発生に設定できるが、元に戻そうとするとE_DEPRECATEDとなるわけです。
var_dump($sqlite3->enableExceptions()); // false(E_DEPRECATED) var_dump($sqlite3->enableExceptions(true)); // false var_dump($sqlite3->enableExceptions(false)); // true(E_DEPRECATED)
Date/Timeにおけるエラーハンドリング強化
PHP 8.3では、Date/Time拡張機能について、固有のエラーと例外を発生するようになりました。以前は、エラーはErrorクラス、例外はExceptionクラスがスローされるだけでしたので、エラーと例外のハンドリングが困難でした。今回、固有のエラーと例外によって、問題発生時のハンドリングが容易になります。
以下の9つのエラー/例外のクラスが追加されています。
Throwable ├── Error | └── DateError | ├── DateObjectError 未初期化のオブジェクトで発生 │ └── DateRangeError 整数値の上限を超えたら発生 └── Exception └── DateException ├── DateInvalidTimeZoneException 不正なタイムゾーン文字列 ├── DateInvalidOperationException DateTimeオブジェクトの不正な操作 ├── DateMalformedStringException 日付/時刻文字列が不正 ├── DateMalformedIntervalStringException 間隔文字列が不正 └── DateMalformedPeriodStringException 期間文字列が不正
DataError派生クラスは、主にコーディングミスなどに由来するエラーにより発生します。ただし、関数などに不正な値が渡された場合のValueError、TypeError、Errorは従来通り発生します。新しいDateErrorクラスを継承するDateObjectErrorとDateRangeErrorは、それぞれ未初期化のオブジェクトの使用、日付処理でエポック値(1970年1月1日午前0時0分0秒からの秒数)がPHPの扱える整数値の上限を超えるような場合に発生します。
DataException派生クラスは、主にタイムゾーン、日付/時刻、間隔(インターバル)、期間(ピリオド)文字列のパースの失敗により発生します。以下のリストは、これらを確かめる例です。
// DateInvalidTimeZoneException $utc_tz = new DateTimeZone("UTC"); // OK $bad_tz = new DateTimeZone("NotValidTZ"); // エラー (1) // エラー:Uncaught DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (NotValidTZ) // DateInvalidOperationException $now_dt = new DateTimeImmutable("2023-11-23 12:34:56 JST"); $seven_day = DateInterval::createFromDateString('7 days'); $now_dt = $now_dt->add($seven_day); // OK $next_thrsday = DateInterval::createFromDateString('next thursday'); $now_dt = $now_dt->sub($next_thrsday); // エラー (2) // エラー:Uncaught DateInvalidOperationException: DateTimeImmutable::sub(): Only non-special relative time specifications are supported for subtraction // DateMalformedStringException $good_dt = new DateTime('now'); // OK $bad_dt = new DateTime('not now'); // エラー (3) // エラー:Uncaught DateMalformedStringException: Failed to parse time string (not now) at position 0 (n): The timezone could not be found in the databas // DateMalformedIntervalStringException $good_di = new DateInterval('P7D'); // OK $bad_di = new DateInterval('now'); // エラー (4) // エラー:Uncaught DateMalformedIntervalStringException: Unknown or bad format (now) in // DateMalformedPeriodStringException $good_dp = new DatePeriod('R4/2023-11-23T00:00:00Z/P7D'); // OK $bad_dp = new DatePeriod('10D'); // エラー (5) // エラー:Uncaught DateMalformedPeriodStringException: Unknown or bad format (10D)
- (1)'UTC'は有効なタイムゾーン文字列ですが、'BadTimeZone'は文字通り不正なタイムゾーン文字列です。
- (2)DateIntervalオブジェクトが「次の木曜日」を意味していますが、DateTimeImmutableオブジェクトに対してsubメソッド(減算)を実行しようとしているので不正な操作となります。
- (3)'now'は有効な日付時刻文字列ですが、'not now'は不正な日付時刻文字列です。
- (4)'P7D'は有効な間隔文字列ですが、'now'は不正な間隔文字列です。
- (5)'R4/2023-11-23T00:00:00Z/P7D'は有効な期間文字列ですが、'10D'は不正な期間文字列です。
まとめ
今回は、PHP 8.3の新機能のうち、クラスや変数の定義、エラーと例外発生に関連する強化ポイントを中心に紹介しました。
次回は、言語仕様や関数の強化・改良ポイントを中心に紹介します。