MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
PHPの基礎 - 例外処理のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
PHPの基礎 - 例外処理
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == 例外処理は、プログラムの実行中に予期せぬエラーが発生した場合、通常の処理フローを中断して特別な対応を行うための仕組みである。<br> PHPでは、エラーが発生した箇所から即座に処理を中断して、適切なエラー処理ルーチンにジャンプすることができる。<br> <br> <code>try</code>ブロックではエラーが発生する可能性のあるコードを配置して、<code>catch</code>ブロックでは発生した例外を受け取って適切な処理を行う。<br> オプションで<code>finally</code>ブロックを追加することができ、例外の発生有無に関わらず必ず実行する処理を記述する。<br> <br> 例外を投げる場合は、<code>throw</code>キーワードを使用する。<br> <br> PHPには、状況に応じた様々な例外クラスが用意されている。<br> * LogicException *: プログラムのロジックに関するエラー * RuntimeException *: 実行時のエラー <br> 独自の例外クラスを定義することにより、アプリケーション固有のエラー状況をより適切に表現できる。<br> 例えば、データベース関連のエラーにはDatabaseException、ファイル操作のエラーにはFileOperationException等、目的に応じた例外クラスを定義できる。<br> <br> 例外処理では、より具体的な例外から順に処理を記述して、最後に一般的な例外を捕捉するという階層的な方法が推奨される。<br> これにより、エラーの種類に応じて適切な対応が可能になる。<br> <br> 捕捉した例外オブジェクトからは、エラーメッセージ、エラーコード、発生場所 (ファイル名と行番号)、スタックトレース等の重要な情報を取得できる。<br> これらの情報は、デバッグやエラーログの記録に活用される。<br> <br> 重大な例外が発生した場合は、システムのログにその内容を記録することが推奨される。<br> ただし、セキュリティ上の観点から、エンドユーザに表示するエラーメッセージには詳細な技術情報を含めないよう注意が必要である。<br> <br> 開発時には、予期できる例外は明示的にキャッチして、適切な対応を実装することが重要である。<br> また、例外を投げ直すことで、より上位の層で統一的なエラー処理を行うことも可能である。<br> <br> <u>※注意</u><br> <u>例外処理は、プログラムの堅牢性を高めるための重要な機能であるが、過度な使用は避けるべきである。</u><br> <u>通常の制御フローとして扱えるケースでは、条件分岐等の一般的な制御構文を使用することが推奨される。</u><br> <br><br> == 基本的な例外処理 == PHPでは、try-catchブロックを使用して例外を処理する。<br> <br> 例外オブジェクトには役立つメソッドが用意されており、<br> getMessageメソッドでエラーメッセージ、getCodeメソッドでエラーコード、getFileメソッドおよびgetLineメソッドでエラーが発生したファイルと行番号を取得できる。<br> <br> <syntaxhighlight lang="php"> try { // 例外が発生する可能性のある処理 throw new Exception("エラーが発生"); } catch (Exception $e) { // 例外を処理する処理 echo $e->getMessage(); } finally { // 必ず実行される処理 } </syntaxhighlight> <br> 以下の例では、複数の例外をキャッチしている。<br> <syntaxhighlight lang="php"> try { // 危険な処理 } catch (DatabaseException $e) { // データベース関連の例外処理 } catch (FileNotFoundException $e) { // ファイル関連の例外処理 } catch (Exception $e) { // その他の例外処理 } </syntaxhighlight> <br> 以下の例では、PDOの例外をキャッチして、ログに記録した後、より適切なカスタム例外を投げ直している。<br> これにより、システム全体で一貫した例外処理が可能になる。<br> <syntaxhighlight lang="php"> try { $pdo = new PDO("mysql:host=localhost;dbname=test", "user", "password"); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id"); $stmt->execute(['id' => $userId]); } catch (PDOException $e) { error_log("データベースエラー: " . $e->getMessage()); throw new DatabaseException("データベース接続に失敗"); } </syntaxhighlight> <br><br> == カスタム例外クラス == 独自の例外クラスを定義することにより、より具体的なエラー処理が可能になる。<br> <br> <syntaxhighlight lang="php"> class DatabaseException extends Exception { public function __construct($message, $code = 0) { parent::__construct($message, $code); } } </syntaxhighlight> <br><br> == バックスラッシュの有無 == * バックスラッシュなし(Exception)の場合 *: まず、現在の名前空間内でExceptionクラスを探す。 *: グローバル名前空間のExceptionクラスにフォールバックする。 * バックスラッシュあり(\Exception)の場合 *: 直接グローバル名前空間のExceptionクラスを参照する。 *: より明示的で安全な記述である。 *: <br> *: 特に名前空間を使用している場合は、バックスラッシュを付けることを推奨する。 *:* 意図しない名前解決の衝突を防げる。 *:* コードの意図が明確になる。 *:* 実行速度がわずかに速くなる。(名前空間の解決プロセスをスキップできるため) <br> <syntaxhighlight lang="php"> try { // 処理 } catch (Exception $e) { // エラー処理 } </syntaxhighlight> <br> <syntaxhighlight lang="php"> try { // 処理 } catch (\Exception $e) { // エラー処理 } </syntaxhighlight> <br> 以下の例のような場合、バックスラッシュを付けることにより、確実にPHPの標準Exceptionクラスを参照することができる。<br> <syntaxhighlight lang="php"> namespace MyApp\Controllers; try { // 処理 } catch (\Exception $e) { // グローバル名前空間のExceptionを明示的に指定 // エラー処理 } </syntaxhighlight> <br><br> == コンストラクタでの例外処理 == PHPでは、コンストラクタでも例外処理が可能である。<br> <br> ただし、以下に示すような注意がある。<br> * コンストラクタで例外が発生した場合、オブジェクトは正しく初期化されない。 * デストラクタは呼ばれない可能性がある。 * 例外が発生した場合、リソースの適切な開放が必要である。 <br> そのため、上記を考慮した安全な実装が必要となる。<br> * 段階的な初期化 *: コンストラクタは単純にして、初期化処理は別メソッドに委譲する。 *: 各初期化ステップを明確に分離する。 * 適切な例外処理 *: 具体的な例外クラスを使用する。 *: 例外の連鎖による詳細なエラー情報を保持する。 *: カスタム例外メッセージによる明確なエラー * リソース管理 *: クリーンアップ処理を実装する。 *: デストラクタでのリソース解放 <br> <syntaxhighlight lang="php"> class DatabaseConnection { private ?PDO $pdo = null; private array $config = []; private string $iniPath; private string $section; /** * DatabaseConnectionの初期化 * * @param string $iniPath 設定ファイルのパス * @param string|null $section 使用するセクション名 * @throws RuntimeException 設定ファイルの読み込みに失敗した場合 * @throws InvalidArgumentException 無効なセクションが指定された場合 */ public function __construct(string $iniPath = 'sample.ini', ?string $section = null) { $this->iniPath = $iniPath; $this->section = $section ?? getenv('APP_ENV') ?: 'development'; // 初期化処理を別メソッドに委譲 $this->initialize(); } // 接続の初期化処理 private function initialize(): void { try { $this->loadConfiguration(); $this->establishConnection(); } catch (Exception $e) { // 初期化中に発生した例外を適切にラップして再スロー $this->cleanup(); throw new RuntimeException("データベース接続の初期化に失敗: " . $e->getMessage(), 0, $e); } } // 設定ファイルの読み込み private function loadConfiguration(): void { if (!file_exists($this->iniPath)) throw new RuntimeException("設定ファイル {$this->iniPath} が存在しない"); $this->config = parse_ini_file($this->iniPath, true); if ($this->config === false) throw new RuntimeException('設定ファイルの読み込みに失敗'); if (!isset($this->config[$this->section])) { throw new InvalidArgumentException("指定されたセクション '{$this->section}' が存在しない"); } } // データベース接続の確立 private function establishConnection(): void { $sectionConfig = $this->config[$this->section]; // 必須パラメータのチェック $requiredParams = ['host', 'dbname']; foreach ($requiredParams as $param) { if (empty($sectionConfig[$param])) { throw new InvalidArgumentException("必須パラメータ {$param} が設定されていない"); } } $host = $sectionConfig['host']; $dbname = $sectionConfig['dbname']; $username = $sectionConfig['username'] ?? 'root'; $password = $sectionConfig['password'] ?? ''; $charset = $sectionConfig['charset'] ?? 'utf8mb4'; $dsn = "mysql:host={$host};dbname={$dbname};charset={$charset}"; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; try { $this->pdo = new PDO($dsn, $username, $password, $options); } catch (PDOException $e) { throw new RuntimeException("データベース接続に失敗: " . $e->getMessage(), 0, $e); } } // リソースのクリーンアップ private function cleanup(): void { $this->pdo = null; $this->config = []; } // デストラクタ public function __destruct() { $this->cleanup(); } // PDO接続を取得 public function getConnection(): PDO { if ($this->pdo === null) throw new RuntimeException('データベース接続が初期化されていない'); return $this->pdo; } // 接続テスト public function testConnection(): bool { try { $this->getConnection()->query('SELECT 1'); return true; } catch (Exception $e) { return false; } } } </syntaxhighlight> <br> <syntaxhighlight lang="php"> // 使用例 try { // データベース接続のインスタンスを作成 $db = new DatabaseConnection(); // 接続テスト if ($db->testConnection()) { echo "データベースへの接続に成功"; // データベース操作の例 $pdo = $db->getConnection(); $stmt = $pdo->query('SELECT version()'); $version = $stmt->fetchColumn(); echo "MySQL バージョン: " . $version; } } catch (Exception $e) { echo "エラー: " . $e->getMessage(); error_log($e->getMessage()); } ?> </syntaxhighlight> <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Web]]
PHPの基礎 - 例外処理
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse