【PHP8.x】DomainException::__construct()メソッドの使い方
__constructメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
__constructメソッドは、DomainExceptionの新しいインスタンスが生成される際に、そのオブジェクトを初期化するために実行されるメソッドです。このメソッドは、DomainExceptionクラスが親クラスであるExceptionから継承しており、例外オブジェクトが持つべき基本的な情報を設定する役割を担います。具体的には、最大で3つのオプション引数を受け取ります。第一引数である$messageには、なぜ例外が発生したのかを人間が理解できるように説明する文字列を指定します。この値は後にgetMessage()メソッドで取得できます。第二引数の$codeには、例外の種類をプログラム的に区別するための整数値を指定し、getCode()メソッドで取得可能です。第三引数の$previousには、この例外がスローされる原因となった、直前に発生した別の例外オブジェクトを指定できます。これにより例外の連鎖を構築し、問題の根本原因を追跡する際に役立ちます。DomainExceptionは、値が定義されたデータドメイン、例えば特定の数値範囲や許容される文字列の集合、に従わない場合に発生する論理的なエラーを示すために使用されます。
構文(syntax)
1public __construct(string $message = "", int $code = 0, ?Throwable $previous = null)
引数(parameters)
string $message = "", int $code = 0, ?Throwable $previous = null
- string $message: 例外発生時の詳細なエラーメッセージを指定する文字列です。
- int $code: 例外に付与するエラーコードを指定する整数です。
- ?Throwable $previous: この例外が別の例外によって引き起こされた場合に、その元の例外を指定します。
戻り値(return)
戻り値なし
戻り値はありません
サンプルコード
PHP 8 コンストラクタプロモーションで例外を扱う
1<?php 2 3declare(strict_types=1); 4 5/** 6 * ユーザー登録に関するドメイン固有の例外クラス 7 * 8 * DomainExceptionを継承し、独自のプロパティを追加しています。 9 */ 10class UserRegistrationException extends DomainException 11{ 12 /** 13 * コンストラクタ 14 * 15 * PHP 8.0 のコンストラクタプロモーション機能を使用しています。 16 * public readonly string $attemptedEmail という記述により、 17 * プロパティの宣言とコンストラクタ内での代入が同時に行われます。 18 * 19 * @param string $attemptedEmail 登録しようとしたメールアドレス 20 * @param string $message 例外メッセージ 21 * @param int $code 例外コード 22 * @param ?Throwable $previous 前の例外 23 */ 24 public function __construct( 25 public readonly string $attemptedEmail, 26 string $message = "", 27 int $code = 0, 28 ?Throwable $previous = null 29 ) { 30 // 親クラスである DomainException のコンストラクタを呼び出す 31 parent::__construct($message, $code, $previous); 32 } 33} 34 35/** 36 * ユーザーを登録する関数(シミュレーション) 37 * 38 * @param string $email 39 * @return void 40 * @throws UserRegistrationException すでにメールアドレスが登録されている場合 41 */ 42function registerUser(string $email): void 43{ 44 // データベースにメールアドレスが既に存在するかをチェックする(ダミー処理) 45 $existingEmails = ['test@example.com']; 46 if (in_array($email, $existingEmails, true)) { 47 // 例外をスローする際に、プロモーションされたプロパティに値を渡す 48 throw new UserRegistrationException( 49 $email, 50 "指定されたメールアドレスは既に使用されています。" 51 ); 52 } 53 54 echo "ユーザー {$email} の登録が成功しました。\n"; 55} 56 57// メイン処理 58try { 59 // 既存のメールアドレスで登録を試みる 60 registerUser('test@example.com'); 61} catch (UserRegistrationException $e) { 62 // catchした例外オブジェクトから、プロモーションされたプロパティに直接アクセスできる 63 echo "エラー: " . $e->getMessage() . "\n"; 64 echo "試行されたメールアドレス: " . $e->attemptedEmail . "\n"; 65 echo "例外がスローされたファイル: " . $e->getFile() . "\n"; 66 echo "例外がスローされた行: " . $e->getLine() . "\n"; 67}
DomainException::__constructは、DomainExceptionクラスのオブジェクトが生成される際に自動的に呼び出される特別なメソッド(コンストラクタ)です。このメソッドは、例外に関する詳細情報を初期化する役割を持ちます。戻り値はありません。
引数には、例外の内容を示す文字列$message、エラーの種類を識別するための整数$code、そしてこの例外が発生する原因となった直前の例外オブジェクトを格納する$previousを指定します。これらの引数はすべてオプションです。
サンプルコードでは、DomainExceptionを継承した独自の例外クラスUserRegistrationExceptionを作成しています。このコンストラクタでは、PHP 8.0の新機能である「コンストラクタプロモーション」が使われています。public readonly string $attemptedEmailという記述により、$attemptedEmailプロパティの宣言とコンストラクタ引数からの値の代入が同時に行われ、コードが簡潔になります。
コンストラクタ内部ではparent::__construct()を呼び出し、受け取った引数を親クラスであるDomainExceptionに渡しています。これにより、catchブロックで例外を捕捉した際に、標準の例外情報に加えて、$e->attemptedEmailのように独自に追加したプロパティにもアクセスでき、より具体的なエラーハンドリングが可能になります。
このコードのpublic readonly string $attemptedEmailという記述は、PHP 8.0から導入されたコンストラクタプロモーションという機能です。プロパティの宣言とコンストラクタでの値の代入を同時に行えるため、コードが簡潔になります。また、子クラスでコンストラクタを定義した場合、親クラスが持つ機能を引き継ぐためにparent::__construct()を呼び出すことが不可欠です。これを忘れると、getMessage()のような基本的なメソッドが期待通りに動作しない原因となります。readonlyを指定したプロパティは、一度初期化されると再代入できなくなるため、意図しない値の変更を防ぎ、コードの安全性を高めるのに役立ちます。
PHP 8 コンストラクタ昇格でカスタム例外を定義する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * 不正なユーザー名が指定されたことを示すカスタム例外クラス。 7 * DomainExceptionを継承し、ドメインロジックのエラーを表します。 8 */ 9class InvalidUsernameException extends DomainException 10{ 11 /** 12 * PHP 8.0で導入された「コンストラクタのプロパティ昇格」を利用しています。 13 * コンストラクタの引数に可視性(public, protected, private)を宣言することで、 14 * プロパティの宣言とコンストラクタ内での代入を同時に行うことができます。 15 * これにより、クラス定義が非常に簡潔になります。 16 * ここでは `$invalidUsername` を public な読み取り専用プロパティとして定義しています。 17 * 18 * @param public readonly string $invalidUsername 不正と判断されたユーザー名 19 * @param string $message 例外メッセージ 20 * @param int $code 例外コード 21 * @param ?Throwable $previous 前の例外 22 */ 23 public function __construct( 24 public readonly string $invalidUsername, 25 string $message = "", 26 int $code = 0, 27 ?Throwable $previous = null 28 ) { 29 // メッセージが指定されていない場合は、デフォルトのメッセージを生成します。 30 if ($message === "") { 31 $message = "指定されたユーザー名 '{$this->invalidUsername}' は無効です。"; 32 } 33 34 // 親クラスである DomainException のコンストラクタを呼び出します。 35 parent::__construct($message, $code, $previous); 36 } 37} 38 39/** 40 * ユーザー名を検証する関数。 41 * 42 * @param string $username 検証するユーザー名 43 * @throws InvalidUsernameException ユーザー名が5文字未満の場合にスローされます。 44 */ 45function validateUsername(string $username): void 46{ 47 echo "ユーザー名 '{$username}' を検証中...\n"; 48 if (mb_strlen($username) < 5) { 49 // 検証に失敗した場合、カスタム例外をスローします。 50 // このとき、不正なユーザー名をコンストラクタに渡します。 51 throw new InvalidUsernameException($username); 52 } 53 echo "ユーザー名 '{$username}' は有効です。\n"; 54} 55 56try { 57 // 正常に処理されるケース 58 validateUsername("php-user"); 59 60 echo "-----\n"; 61 62 // 例外がスローされるケース 63 validateUsername("bad"); 64} catch (InvalidUsernameException $e) { 65 // InvalidUsernameException をキャッチします。 66 echo "エラーをキャッチしました。\n"; 67 echo "メッセージ: " . $e->getMessage() . "\n"; 68 // コンストラクタのプロパティ昇格で定義したプロパティに直接アクセスできます。 69 echo "問題のユーザー名: " . $e->invalidUsername . "\n"; 70 echo "例外コード: " . $e->getCode() . "\n"; 71 echo "ファイル: " . $e->getFile() . " (" . $e->getLine() . "行目)\n"; 72}
このサンプルコードは、DomainExceptionクラスのコンストラクタ__constructを継承して、アプリケーション固有の例外クラスInvalidUsernameExceptionを作成する例を示しています。__constructは、newキーワードで例外オブジェクトが生成される際に自動的に呼び出されるメソッドで、戻り値はありません。
このコードの大きな特徴は、PHP 8で導入された「コンストラクタのプロパティ昇格」を利用している点です。InvalidUsernameExceptionのコンストラクタでは、引数にpublic readonly string $invalidUsernameと宣言するだけで、invalidUsernameという公開プロパティを定義し、渡された引数の値で初期化までを同時に行っています。これにより、クラスの記述を大幅に簡潔にできます。
コンストラクタは、第一引数として不正なユーザー名$invalidUsernameを受け取ります。第二引数$messageは例外メッセージ、第三引数$codeはエラーコード、第四引数$previousは連鎖する前の例外を指定するためのもので、これらは親クラスであるDomainExceptionのコンストラクタに渡されます。try...catchブロックでは、条件に合わないユーザー名が指定されるとInvalidUsernameExceptionが生成・スローされます。catchブロックでは、getMessage()メソッドでメッセージを取得できるだけでなく、プロパティ昇格で定義した$e->invalidUsernameのように、エラーの原因となったデータへ直接アクセスして、より詳細なエラー処理を行うことが可能です。
このサンプルコードの注意点は、PHP 8.0から導入された「コンストラクタのプロパティ昇格」という構文を利用している点です。コンストラクタの引数にpublicなどの可視性を付けると、プロパティ宣言と値の代入が同時に行われ、コードが簡潔になります。古いバージョンのPHPでは動作しないため注意してください。また、readonlyを付けるとプロパティは読み取り専用となり、一度初期化されると再代入できなくなるため、意図しない値の変更を防げます。例外クラスを継承した際は、親のコンストラクタparent::__construct()を呼び出すことが重要です。これを忘れると、例外のメッセージなどが正しく設定されず、エラー処理が正常に機能しなくなる可能性があります。