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 completefinally ブロックは、try または catch ブロック内から return した場合でも実行されるため、重要な cleanup 操作に安心して使用できます。
チャレンジ
簡単try-catch-finally が連携してエラーを適切に処理しながら、確実にクリーンアップが always 実行される仕組みを示すファイル処理システムを構築しましょう。
コードを3つのファイルに分けて整理します。
FileException.php:Exceptionを extends するカスタムFileExceptionclass を Create します。これはシステム内のファイル関連エラーを表します。FileProcessor.php: ファイル操作をシミュレートするFileProcessorclass を Create します。FileException ファイルを含めます。class には次の要素を用意します。$isOpenに初期値falseが設定された private boolean プロパティ$isOpenをtrueに設定し、"Opening: [filename]"を出力するメソッドopen(string $filename): void。filename が"invalid.txt"の場合は、メッセージ"Cannot open file"を指定してFileExceptionを throw します"Processing file..."を出力するメソッドprocess(): void。$isOpenがfalseの場合は、メッセージ"File not open"を指定してRuntimeExceptionを throw します$isOpenをfalseに設定し、"File closed"を出力するメソッドclose(): void- 現在の状態を返すメソッド
isOpen(): bool
main.php: FileProcessor ファイルを含めます。1つの入力として filename を受け取ります。FileProcessorを Create し、try-catch-finally構造を使用して次の処理を行います。tryblock では、filename を指定してopen()を call し、その後process()を call します- 最初に
FileExceptionを Catch し、"File error: [message]"を出力します RuntimeExceptionを Catch し、"Runtime error: [message]"を出力しますfinallyblock では、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"
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: PHPオンラインコンパイラ