【PHP8.x】DomainException::fileプロパティの使い方
fileプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
fileプロパティは、例外がスローされたファイル名を保持するプロパティです。このプロパティは、PHPのすべての例外クラスの基底となるExceptionクラスで定義されており、DomainExceptionクラスはこれを継承しています。プログラムの実行中にDomainExceptionが発生すると、PHPエンジンは例外が生成されたソースコードが含まれるファイルのフルパスをこのプロパティに自動的に設定します。開発者はこの情報を利用することで、エラーが発生した正確な場所を迅速に特定できます。これは、特に規模の大きなアプリケーションや複雑なコードベースで問題の原因を調査する際のデバッグ作業において、非常に重要な役割を果たします。なお、このfileプロパティはprotectedスコープで宣言されているため、オブジェクトの外部から直接アクセスすることは推奨されません。プロパティの値を取得する際には、代わりに公開されているgetFile()メソッドを使用するのが一般的です。
構文(syntax)
1<?php 2 3try { 4 // DomainExceptionを意図的にスローします。 5 throw new DomainException("ドメインエラー"); 6} catch (DomainException $e) { 7 // fileプロパティの値は、getFile()メソッドで取得します。 8 $fileName = $e->getFile(); 9 // 例外が発生したファイル名を出力します。 10 echo $fileName; 11}
引数(parameters)
引数なし
引数はありません
戻り値(return)
string
DomainExceptionクラスのfileプロパティは、例外が発生したファイル名を文字列で返します。
サンプルコード
PHPのfile_existsでファイル存在チェックし例外を投げる
1<?php 2 3declare(strict_types=1); 4 5/** 6 * 設定ファイルを読み込むクラス 7 */ 8class ConfigLoader 9{ 10 /** 11 * @var string 設定ファイルのパス 12 */ 13 private string $filePath; 14 15 public function __construct(string $filePath) 16 { 17 $this->filePath = $filePath; 18 } 19 20 /** 21 * 設定を読み込みます。 22 * ファイルが存在しない場合は DomainException をスローします。 23 * 24 * @return string ファイルの内容 25 * @throws DomainException ファイルが存在しない場合 26 */ 27 public function load(): string 28 { 29 // file_exists() を使ってファイルの存在を確認します。 30 if (!file_exists($this->filePath)) { 31 // ファイルが存在しないのは、この処理のドメイン(前提条件)に反するため、 32 // DomainException をスローします。 33 throw new DomainException("設定ファイルが見つかりません: {$this->filePath}"); 34 } 35 36 // 実際にはファイルの内容を解析しますが、この例では内容をそのまま返します。 37 return file_get_contents($this->filePath); 38 } 39} 40 41// 存在しないファイルパスを指定します。 42$nonExistentFile = 'config.json.missing'; 43 44try { 45 // 存在しないファイルを読み込もうとします。 46 echo "--- 存在しないファイル '{$nonExistentFile}' の読み込み試行 ---" . PHP_EOL; 47 $loader = new ConfigLoader($nonExistentFile); 48 $config = $loader->load(); 49 echo "読み込み成功: " . $config . PHP_EOL; 50} catch (DomainException $e) { 51 // 例外をキャッチします。 52 echo "エラーが発生しました。" . PHP_EOL; 53 echo "メッセージ: " . $e->getMessage() . PHP_EOL; 54 55 // DomainException (親の Exception から継承) の getFile() メソッドで 56 // 例外がスローされたファイル名を取得できます。 57 // これはリファレンス情報の 'file' プロパティに対応します。 58 echo "発生ファイル: " . $e->getFile() . PHP_EOL; 59 echo "発生行: " . $e->getLine() . PHP_EOL; 60} 61 62echo PHP_EOL; 63 64// 存在するダミーファイルを作成して試します。 65$existentFile = 'dummy_config.txt'; 66file_put_contents($existentFile, '{"key":"value"}'); 67 68try { 69 echo "--- 存在するファイル '{$existentFile}' の読み込み試行 ---" . PHP_EOL; 70 $loader = new ConfigLoader($existentFile); 71 $config = $loader->load(); 72 echo "読み込み成功: " . $config . PHP_EOL; 73} catch (DomainException $e) { 74 // こちらは成功するため、このブロックは実行されません。 75 echo "エラー: " . $e->getMessage() . PHP_EOL; 76} finally { 77 // 後片付けとしてダミーファイルを削除します。 78 if (file_exists($existentFile)) { 79 unlink($existentFile); 80 } 81}
このPHPサンプルコードは、プログラムの前提条件が満たされない場合に DomainException という種類の例外を発生させる方法を示しています。
コードの中心は ConfigLoader クラスです。このクラスは、指定されたパスから設定ファイルを読み込む役割を持ちます。load メソッドの中では、まずPHPの file_exists 関数を使ってファイルが実際に存在するかを確認します。もしファイルが存在しない場合、それは「設定ファイルが存在する」というこの処理の前提条件(ドメイン)に反するため、new DomainException(...) でエラーを意図的に発生させ、処理を中断します。
try...catch ブロックは、この発生した例外を捕まえるための構文です。存在しないファイルを読み込もうとすると DomainException が発生し、catch ブロック内の処理が実行されます。
ここで、$e->getFile() メソッドを呼び出しています。これはリファレンスにある file プロパティの値を取得するもので、例外が発生したPHPスクリプトのファイル名を文字列として返します。これにより、プログラムのどこでエラーが起きたのかを特定できます。同様に $e->getLine() で発生箇所の行番号も取得できます。
ファイル操作を行う際は、処理の前に file_exists() でファイルの存在を確認することが重要です。これにより、ファイルが見つからない場合に発生する警告(Warning)を防ぎ、プログラムが意図せず停止するリスクを減らせます。エラーが発生しうる処理は try-catch ブロックで囲むことで、例外を捕捉して適切に対応できます。サンプルで使われている DomainException は、プログラムの前提条件に反する状況を示すための例外です。注意点として、catch ブロックで使う $e->getFile() メソッドは、例外が作られたPHPスクリプトのファイル名を返すものであり、読み込もうとして失敗したファイルパスそのものを返すわけではない点を理解しておく必要があります。
DomainExceptionでファイル検証するPHPコード
1<?php 2 3declare(strict_types=1); 4 5/** 6 * 指定されたファイルの内容を検証し、無効な場合は DomainException をスローします。 7 * 8 * @param string $filepath 検証するファイルのパス 9 * @return void 10 * @throws DomainException ファイルが存在しないか、内容が 'VALID' でない場合にスローされます。 11 */ 12function validateFileContent(string $filepath): void 13{ 14 // ファイルが存在するかどうかを確認します。 15 if (!file_exists($filepath)) { 16 throw new DomainException("ファイル '{$filepath}' が存在しません。"); 17 } 18 19 // キーワード `file_get_contents` を使用してファイルの内容を文字列として読み込みます。 20 $content = file_get_contents($filepath); 21 22 // ファイルの内容が期待するドメイン(ここでは 'VALID' という文字列)に属しているか検証します。 23 if (trim($content) !== 'VALID') { 24 // 値が期待されるドメインに属していない場合、DomainException をスローします。 25 throw new DomainException("ファイルの内容が不正です。期待値: 'VALID'"); 26 } 27 28 echo "ファイル '{$filepath}' の内容は正常です。\n"; 29} 30 31// --- 以下、サンプルコードの実行部分 --- 32 33// 検証に使用する一時ファイルの名前 34$tempFile = 'data.tmp'; 35 36try { 37 // DomainException を発生させるために、わざと無効なデータをファイルに書き込みます。 38 file_put_contents($tempFile, 'INVALID'); 39 40 // ファイル内容を検証する関数を呼び出します。 41 validateFileContent($tempFile); 42} catch (DomainException $e) { 43 // スローされた DomainException をキャッチします。 44 echo "エラーを捕捉しました。\n"; 45 echo "メッセージ: " . $e->getMessage() . "\n"; 46 47 // DomainException->file プロパティに対応する getFile() メソッドを呼び出します。 48 // これは、例外がスローされたPHPスクリプトファイル自身のパスを返します。 49 echo "例外発生ファイル: " . $e->getFile() . "\n"; 50 echo "例外発生行: " . $e->getLine() . "\n"; 51} finally { 52 // 処理の最後に、作成した一時ファイルを必ず削除します。 53 if (file_exists($tempFile)) { 54 unlink($tempFile); 55 } 56}
このPHPサンプルコードは、ファイルの内容を検証し、その値が期待される定義された範囲(ドメイン)にない場合に DomainException という種類の例外を発生させる例です。
validateFileContent 関数は、file_get_contents 関数を使用して、指定されたファイルの内容を一つの文字列として読み込みます。そして、読み込んだ内容が 'VALID' という文字列でない場合、プログラムの処理を中断し、DomainException を発生させます。
try...catch ブロックでは、このエラーを意図的に発生させて捕捉する流れを示しています。catch ブロックで DomainException のインスタンスである変数 $e を受け取ると、そのプロパティにアクセスできます。$e->getFile() メソッドは、例外がどのPHPスクリプトファイルで発生したかを知るためのものです。このメソッドには引数はなく、戻り値としてファイルパスを示す文字列を返します。これは DomainException クラスが持つ file プロパティの値を取得するもので、エラーの原因を特定する際に重要な情報となります。
DomainExceptionのgetFile()メソッドが返すファイルパスは、処理対象のファイル(data.tmp)ではなく、例外が投げられたPHPスクリプト自身のパスである点に注意してください。file_get_contents関数はファイルの読み込みに失敗するとfalseを返すため、関数の実行後に戻り値がfalseでないかを確認するのがより安全な方法です。サンプルではtry...catch構文を使い、エラーが発生してもプログラムが停止しないようにしています。特にfinallyブロックは、例外の有無にかかわらず必ず実行されるため、一時ファイルの削除のような、処理の最後に必ず行いたい後始末を記述するのに非常に重要です。