【PHP8.x】LogicException::__construct()メソッドの使い方
__constructメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『__constructメソッドは、新しいLogicExceptionオブジェクトを生成し、その状態を初期化するために実行されるメソッドです』
このメソッドはPHPにおける「コンストラクタ」として機能し、new LogicException()という構文でクラスのインスタンスが作成される際に自動的に呼び出されます。その主な役割は、例外に関する詳細情報を設定することです。具体的には、3つの引数を受け取ることができます。第1引数 $message には、なぜこの例外が発生したのかを説明する文字列を指定します。このメッセージは、後のデバッグ作業で非常に重要な情報となります。第2引数 $code には、例外の種類を識別するための整数値を指定します。これにより、catchブロックで特定の種類の例外を判別し、処理を分岐させることが可能になります。第3引数 $previous には、この例外がスローされる直前にキャッチされた別の例外オブジェクトを指定します。これは例外チェーンを構築するために使用され、エラーの根本原因を追跡するのに役立ちます。これらの引数はすべてオプションであり、必要に応じて省略することもできます。LogicExceptionは、プログラムのロジックに問題があることを示すために使用されるため、このコンストラクタを通じて、開発者がエラーの原因を特定しやすくなるように、明確な情報を持つ例外オブジェクトを生成することが推奨されます。
構文(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: この例外が発生する直前に捕捉された別の例外がある場合、その例外オブジェクトを指定します。存在しない場合は
nullです。
戻り値(return)
戻り値なし
戻り値はありません
サンプルコード
PHP 8 コンストラクタプロパティプロモーションによる例外処理
1<?php 2 3declare(strict_types=1); 4 5/** 6 * 独自のロジック例外クラス。 7 * LogicExceptionを継承し、PHP 8.0の「コンストラクタプロパティプロモーション」を利用しています。 8 */ 9class InvalidOperationException extends LogicException 10{ 11 /** 12 * コンストラクタ。 13 * 14 * public readonly string $operation のように可視性キーワードを付けることで、 15 * プロパティの宣言とコンストラクタ引数からの値の代入を同時に行います。 16 * これが「コンストラクタプロパティプロモーション」です。 17 * 18 * @param string $message 例外メッセージ (親クラスから継承) 19 * @param int $code 例外コード (親クラスから継承) 20 * @param string $operation エラーが発生した操作名 (このクラス独自のプロパティ) 21 * @param ?Throwable $previous 直前の例外 (親クラスから継承) 22 */ 23 public function __construct( 24 string $message = "", 25 int $code = 0, 26 public readonly string $operation = 'unknown', // コンストラクタプロパティプロモーション 27 ?Throwable $previous = null 28 ) { 29 // 親クラス (LogicException) のコンストラクタを呼び出し、 30 // message, code, previous プロパティを初期化する。 31 parent::__construct($message, $code, $previous); 32 } 33} 34 35// 関数の実行と例外処理のデモ 36try { 37 $userRole = 'guest'; 38 39 // 管理者権限が必要な操作をゲストが試みたと仮定 40 if ($userRole !== 'admin') { 41 // カスタム例外をスローする 42 // コンストラクタで独自プロパティ operation を指定 43 throw new InvalidOperationException( 44 message: 'この操作を実行する権限がありません。', 45 code: 403, 46 operation: 'delete_user' 47 ); 48 } 49 50 echo "ユーザーを削除しました。\n"; 51 52} catch (InvalidOperationException $e) { 53 // スローされたカスタム例外をキャッチ 54 echo "エラーが発生しました。\n"; 55 echo "--------------------\n"; 56 // コンストラクタプロパティプロモーションで定義したプロパティにアクセス 57 echo "失敗した操作: " . $e->operation . "\n"; 58 echo "エラーメッセージ: " . $e->getMessage() . "\n"; 59 echo "エラーコード: " . $e->getCode() . "\n"; 60 echo "発生ファイル: " . $e->getFile() . "\n"; 61 echo "発生行: " . $e->getLine() . "\n"; 62}
LogicExceptionのコンストラクタ__constructは、プログラムの論理的な誤りを示す例外オブジェクトを生成し、初期化するために呼び出されるメソッドです。コンストラクタであるため、特定の戻り値はありません。
引数として、例外に関する詳細な情報を渡すことができます。第一引数$messageにはエラー内容を説明する文字列を、第二引数$codeにはエラーの種類を識別するための整数値を設定します。第三引数$previousは、例外が連鎖して発生した場合に、その直前の例外オブジェクトを指定するために使用します。
サンプルコードでは、LogicExceptionを継承してInvalidOperationExceptionという独自の例外クラスを定義しています。このクラスのコンストラクタでは、PHP 8.0の新機能「コンストラクタプロパティプロモーション」が利用されています。引数リストでpublic readonly string $operationと宣言することにより、プロパティの定義とコンストラクタ引数からの値の代入を同時に行い、コードを簡潔にしています。
コンストラクタの内部ではparent::__construct()を呼び出し、親クラスであるLogicExceptionが持つプロパティ(messageやcode)を初期化しています。これにより、独自の情報を追加しつつ、基本的な例外の機能を引き継いだ、より詳細な例外処理が可能になります。
コンストラクタプロパティプロモーションは、プロパティの宣言と初期化を同時に行える便利な機能です。子クラスでコンストラクタを定義する際は、サンプルコードのように parent::__construct() を呼び出し、親クラスが持つプロパティを初期化することを忘れないでください。これを省略すると、getMessage() などで期待した値が取得できなくなります。この機能はPHP 8.0から導入されたもので、readonly 修飾子はPHP 8.1からの機能のため、古いPHPバージョンでは動作しない点にも注意が必要です。このように独自の例外クラスを作成することで、エラーの種類に応じた具体的な処理を catch ブロックで記述できるようになります。
PHPカスタム例外の__constructでparentを呼び出す
1<?php 2 3declare(strict_types=1); 4 5/** 6 * アプリケーション固有のロジックエラーを表すカスタム例外クラス。 7 * PHPの標準例外クラスである LogicException を継承します。 8 */ 9class ApplicationLogicException extends LogicException 10{ 11 /** 12 * 新しい例外インスタンスを生成します。 13 * 14 * このコンストラクタ(__construct)は、受け取った引数をそのまま 15 * 親クラス(LogicException)のコンストラクタに渡します。 16 * `parent::__construct()` を呼び出すことで、親クラスが持つ 17 * 例外メッセージやコードなどのプロパティを正しく初期化できます。 18 * 19 * @param string $message この例外で説明するエラーメッセージ 20 * @param int $code エラーを識別するためのコード 21 * @param ?Throwable $previous 連鎖する前の例外 22 */ 23 public function __construct(string $message = "", int $code = 0, ?Throwable $previous = null) 24 { 25 // parentキーワードを使い、親クラスであるLogicExceptionのコンストラクタを呼び出します。 26 parent::__construct($message, $code, $previous); 27 } 28} 29 30/** 31 * ユーザー登録を試みる関数。 32 * 33 * @param string $username 登録するユーザー名 34 * @throws ApplicationLogicException ユーザー名が不正な場合にスローされる 35 */ 36function registerUser(string $username): void 37{ 38 // ユーザー名が空かどうかというロジックをチェックします。 39 if (empty($username)) { 40 // ロジックに反する場合、カスタム例外をスローします。 41 // ここで ApplicationLogicException のコンストラクタが呼び出されます。 42 throw new ApplicationLogicException("ユーザー名を空にすることはできません。", 101); 43 } 44 echo "ユーザー '{$username}' は正常に登録されました。\n"; 45} 46 47// --- 実行コード --- 48 49try { 50 // 正常なケース 51 registerUser("Taro"); 52 53 // 例外が発生するケース 54 registerUser(""); 55} catch (ApplicationLogicException $e) { 56 // スローされた例外をキャッチします。 57 echo "エラーをキャッチしました。\n"; 58 echo "メッセージ: " . $e->getMessage() . "\n"; 59 echo "コード: " . $e->getCode() . "\n"; 60} 61 62?>
このサンプルコードは、PHPの標準例外クラスであるLogicExceptionを継承して、アプリケーション独自の例外クラスApplicationLogicExceptionを作成する方法を説明します。
__constructメソッドは、newキーワードでクラスのインスタンスが生成される際に自動的に呼び出される、初期化のための特別なメソッド(コンストラクタ)です。
このApplicationLogicExceptionクラスでは、自身のコンストラクタ内でparent::__construct()を呼び出しています。parentキーワードは親クラスであるLogicExceptionを指します。これにより、親クラスのコンストラクタに処理を委ね、例外が持つべき基本的なプロパティを正しく設定しています。
引数には、エラー内容を説明する文字列$message、エラーの種類を識別するための整数$code、そして例外が連鎖する場合に直前の例外を保持する$previousを受け取ります。コンストラクタはインスタンスの初期化が目的のため、戻り値はありません。
実行コード部分では、不正な引数で関数を呼び出した際にこのカスタム例外をスローし、catchブロックで捕捉しています。そして、コンストラクタで設定されたエラーメッセージとコードをgetMessage()とgetCode()メソッドで取得・表示しています。
クラスを継承して独自のコンストラクタ(__construct)を定義する場合、parent::__construct()を呼び出すことが重要です。これを呼び出すことで、親クラスが持つ初期化処理(この例では例外メッセージやエラーコードの設定)が実行され、オブジェクトが正しく機能します。もしこの呼び出しを忘れると、親クラスのプロパティが初期化されず、getMessage()メソッドなどが期待通りに動作しない原因となります。__constructはオブジェクトがnewで生成される際に一度だけ自動的に呼ばれる特別なメソッドです。parentキーワードは、継承元の親クラスを指すためのもので、親のメソッドを呼び出す際に使います。この仕組みは、既存のクラスの機能を拡張しつつ、基本的な動作を確実に引き継ぐために不可欠です。