PHP - OOP - 7. 例外処理(try - catch文)
引き続き例外について学習していきましょう。ここではスローされた Exception
インスタンスをキャッチ(捕捉)して処理を継続する方法を学習します。
例外処理(try - catch文)の記述
これまでに学習してきたとおり Exception
インスタンスは throw
キーワードによってスローできます。たとえば MyClass
クラスの myMethod
の中で引数 $x
が空文字の場合に Excetpion
インスタンスをスローするとしましょう。
<?php
class MyClass
{
public $myProperty;
public function __construct($value)
{
$this->myProperty = $value;
}
public function myMethod($x)
{
if ($x == "") {
$e = new Exception("Invalid argument.");
throw $e;
}
echo $this->myProperty . " " . $x;
}
}
この myMethod
からスローされた Exception
インスタンスはメソッドの呼び出し元( my_class_runner.php
)において try - catch
文を実装することでキャッチできます。
<?php
require_once("MyClass.php");
try {
$myClass = new MyClass("Hello");
$myClass->myMethod(""); #=> throw Exception
} catch (Exception $e) {
echo "Catch exception." . PHP_EOL;
}
try - catch
文はスローされた例外をキャッチするために使用します。
try {
// 例外の発生する可能性のある処理
} catch (キャッチ対象の例外クラス名 変数名) {
// 例外発生時の処理
}
try
の処理ブロック {}
の中で例外がスローされると後の catch
の処理ブロック {}
に処理が移ります。このとき catch
引数 (Exception $e)
にはスローされた Exception
インスタンスが代入されます。このプログラムを実行すると画面に Catch exception.
と出力されます。
try - catch
文の動作イメージを使うために次のプログラム( my_class_runner.php
)の実行結果も考えてみましょう。
<?php
require_once("MyClass.php");
echo "1";
try {
$myClass = new MyClass("Hello");
$myClass->myMethod(""); #=> throw Exception
echo "2";
} catch (Exception $e) {
echo "3";
}
echo "4";
このプログラムでは $myClass->myMethod("");
の呼び出しで Exception
インスタンスがスローされます。そのため処理は catch
ブロックに移るため、 echo "2";
は実行されません。この場合の実行結果は 134
となります。
また $myClass->myMethod("Andy");
と変更した場合はどうでしょうか。
<?php
require_once("MyClass.php");
echo "1";
try {
$myClass = new MyClass("Hello");
$myClass->myMethod("Andy"); #=> Hello Andy
echo "2";
} catch (Exception $e) {
echo "3";
}
echo "4";
この場合は Exception
インスタンスはスローされないため実行結果は 1Hello Andy24
となります。
PHPプログラムの開発(try - catch文)
それでは計算機プログラムの呼び出し時に例外処理( try - catch
文)を実装してみましょう。まずは前節までの計算機クラス( SimpleCalc
クラス)を確認しておきましょう。
<?php
class SimpleCalc
{
// ...省略
public function divide($x)
{
if ($x == 0) {
$e = new Exception("Divide by 0.");
throw $e;
}
$this->number = $this->number / $x;
}
// ...省略
}
上記のように divide
メソッドで 0
による除算の発生時に Exception
インスタンスをスローしています。計算機クラス( SimpleCalc
クラス)に修正はありません。
次に実行プログラム( calc_runner.php
)を修正します。
<?php
require_once("SimpleCalc.php");
try {
$calc = new SimpleCalc();
$calc->add(10);
$calc->subtract(5);
$calc->multiply(10);
$calc->divide(0);
$calc->show();
} catch (Exception $e) {
echo "Exception: " . $e->getMessage() . PHP_EOL;
}
try
ブロックの中でスローされた Exception
インスタンスは catch
ブロックの引数( $e
)に代入されます。変数 $e
は Exception
クラスのインスタンスであるため、 Exception
クラスに定義されているメソッド( getMessage
メソッドなど)を呼び出すことができます。
Exception
クラスのgetMessage
メソッドは戻り値にコンストラクタで指定されたメッセージを返します。
それではコマンドラインからプログラムを実行してみましょう。
$ php calc_runner.php
Exception: Divide by 0.
実行結果からスローされた Exception
インスタンスを catch
ブロックで処理できているのがわかります。
参考:finallyブロックの使用
PHP5.5以降は try - catch
文に finally
ブロックを追加することもできます。
<?php
require_once("SimpleCalc.php");
try {
$calc = new SimpleCalc();
$calc->add(10);
$calc->subtract(5);
$calc->multiply(10);
$calc->divide(0);
$calc->show();
} catch (Exception $e) {
echo "Exception: " . $e->getMessage() . PHP_EOL;
} finally {
echo "finally" . PHP_EOL;
}
finally
ブロックは例外発生の有無に関わらず動作します。
まとめ
- スローされた例外(
Exception
クラスのインスタンス)はtry - catch
文で処理できる try
ブロックの中で例外が発生するとcatch
ブロックに処理が移るcatch
ブロックの定義にはキャッチ対象の例外クラス名と、発生した例外インスタンスを格納する変数を定義する