Menu
Coddy logo textTech

Try、Catch、Finally

CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 68/91。

例外を作成してスローする方法がわかったので、次は例外をcatchする方法を学ぶ必要があります。try-catch-finally構造を使うと、例外によってアプリケーションがクラッシュするのを防ぎ、適切に処理できます。

例外をスローする可能性のあるコードをtryブロックで囲み、その後catchブロックで例外を処理します。

<?php
class Calculator {
    public function divide(int $a, int $b): float {
        if ($b === 0) {
            throw new InvalidArgumentException("Cannot divide by zero");
        }
        return $a / $b;
    }
}

$calc = new Calculator();

try {
    echo $calc->divide(10, 0);
} catch (InvalidArgumentException $e) {
    echo "Error: " . $e->getMessage();
}

出力:

Error: Cannot divide by zero

複数の catch ブロックを使って、異なる例外型を捕捉できます。PHP はそれらを順番にチェックするため、より具体的な例外を先に配置してください。

<?php
try {
    // 危険なコード
} catch (InvalidArgumentException $e) {
    echo "Bad input: " . $e->getMessage();
} catch (Exception $e) {
    echo "Something went wrong: " . $e->getMessage();
}

finally ブロックは、例外がスローされたか、Caught されたかにかかわらず実行されます。接続を閉じるなどの cleanup タスクに最適です。

<?php
try {
    echo "Attempting operation\n";
    throw new Exception("Failed");
} catch (Exception $e) {
    echo "Caught: " . $e->getMessage() . "\n";
} finally {
    echo "Cleanup complete";
}

出力:

Attempting operation
Caught: Failed
Cleanup complete

finally ブロックは、try または catch ブロック内から return した場合でも実行されるため、重要な cleanup 操作に安心して使用できます。

challenge icon

チャレンジ

簡単

try-catch-finally が連携してエラーを適切に処理しながら、確実にクリーンアップが always 実行される仕組みを示すファイル処理システムを構築しましょう。

コードを3つのファイルに分けて整理します。

  • FileException.php: Exception を extends するカスタム FileException class を Create します。これはシステム内のファイル関連エラーを表します。
  • FileProcessor.php: ファイル操作をシミュレートする FileProcessor class を Create します。FileException ファイルを含めます。class には次の要素を用意します。
    • $isOpen に初期値 false が設定された private boolean プロパティ
    • $isOpentrue に設定し、"Opening: [filename]" を出力するメソッド open(string $filename): void。filename が "invalid.txt" の場合は、メッセージ "Cannot open file" を指定して FileException を throw します
    • "Processing file..." を出力するメソッド process(): void$isOpenfalse の場合は、メッセージ "File not open" を指定して RuntimeException を throw します
    • $isOpenfalse に設定し、"File closed" を出力するメソッド close(): void
    • 現在の状態を返すメソッド isOpen(): bool
  • main.php: FileProcessor ファイルを含めます。1つの入力として filename を受け取ります。

    FileProcessor を Create し、try-catch-finally 構造を使用して次の処理を行います。

    • try block では、filename を指定して open() を call し、その後 process() を call します
    • 最初に FileException を Catch し、"File error: [message]" を出力します
    • RuntimeException を Catch し、"Runtime error: [message]" を出力します
    • finally block では、isOpen() を使用してファイルが開いているか check し、開いている場合は close() を call します。その後、"Cleanup complete" を出力します

finally block により、操作が成功した場合でも失敗した場合でも cleanup が実行されます。このパターンは、処理中に何が起きたかにかかわらず cleanup を実行する必要がある、ファイル、データベース接続、ネットワークソケットなどのリソースを管理するうえで不可欠です。

自分で試してみよう

<?php
require_once 'FileProcessor.php';

// 入力を読み取る
$filename = trim(fgets(STDIN));

// TODO: FileProcessor のインスタンスを作成する

// TODO: try-catch-finally 構造を使用する:
// - try ブロック内: filename で open() を呼び出し、次に process() を呼び出す
// - 最初に FileException をキャッチし、"File error: [message]" を出力する
// - RuntimeException をキャッチし、"Runtime error: [message]" を出力する
// - finally ブロック内: isOpen() を使ってファイルが開いているか確認し、開いていれば close() を呼び出す
//   Then print "Cleanup complete"

?>
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: PHPオンラインコンパイラ