PHP - OOP - 6. 例外(Exception) - 1/2

ここからは例外( Exception )について学習します。例外( Exception )とはプログラムの予期せぬ事態を通知する仕組みです。例外とよく似た言葉にエラーがありますが、一般的に、PHPのエラーとは復旧することのできない致命的な問題を意味します。一方の例外は想定外の事態を意味しますが、適切に対処することで処理を継続することも可能となります。

例外の仕組み

PHPには例外を扱うためのクラスとして Exception クラスが用意されています。 Exception クラスのインスタンスを生成することで、プログラムの中で例外を生成できます。

$e = new Exception();

また Exception クラスには例外メッセージを引数にとるコンストラクタも用意されているので、次のように Exception インスタンスを生成できます。

$e = new Exception("Exctption message.");

生成した例外インスタンスは throw キーワードによって通知できます。

$e = new Exception("Exctption message.");
throw $e;

PHPでは例外を通知することを「例外をスローする」と言います。スローされた例外インスタンスは後で紹介する try - catch 構文によって処理できるようになっています。

PHPプログラムの開発(0による除算)

それでは簡単な計算機クラス( SimpleCalc.php )を題材に例外について考えてみましょう。これまでに加算処理を行う add メソッドを実装しているので、ここでは新たに以下の3つのメソッドを追加して四則演算を完成させます。

  • subtractメソッド(減算)
  • multiplyメソッド(乗算)
  • divideメソッド(除算)
<?php
class SimpleCalc
{
    // 省略

    public function add($x)
    {
        $this->number = $this->number + $x;
    }

    public function subtract($x)
    {
        $this->number = $this->number - $x;
    }

    public function multiply($x)
    {
        $this->number = $this->number * $x;
    }

    public function divide($x)
    {
        $this->number = $this->number / $x;
    }

    public function show()
    {
        echo $this->number . PHP_EOL;
    }
}

ここでは除算を行う divide メソッドに注目してください。 divide メソッドの引数に 0 を指定すると 、 0 による除算が発生します。このような演算は行えないため、PHPは実行時に Warning メッセージを出力します。

実行プログラム( calc_runner.php )を以下のように修正してみましょう。

<?php
require_once("SimpleCalc.php");

$calc = new SimpleCalc();

$calc->add(10);
$calc->subtract(5);
$calc->multiply(10);
$calc->divide(0); // Warning!

$calc->show();

ここでは $calc->divide(0) と呼び出している部分で 0 による除算が発生し、戻り値には無限を表す定数 INF が返却されます。コマンドラインからプログラムを実行してみましょう。

$ php calc_runner.php
Warning: Division by zero in /Users/your_name/Desktop/code-php/SimpleCalc.php on line 40
INF

PHPにおける Warning メッセージはエラーとは異なります。メッセージは出力されるものの、後続の処理は継続されるようになっています。

PHPプログラムの開発(例外の生成)

次に計算機クラス( SimpleCalc クラス)の除算を行う divide メソッドを修正して、 0 による除算が発生した場合は演算を行う前に例外( Exception インスタンス)をスローするように修正します。

<?php
class SimpleCalc
{
    // ...省略

    public function divide($x)
    {
        if ($x == 0) {
            $e = new Exception("Divide by 0.");
            throw $e;
        }
        $this->number = $this->number / $x;
    }

    // ...省略
}

divide メソッドでは引数 $x の値が 0 の場合、 Exception インスタンスを生成して、 throw キーワードによって例外をスローしています。 throw キーワードは return キーワードのように、呼び出されるた時点でメソッドの処理を終了します。

計算機クラス( SimpleCalc.php )を修正したので、もう一度、実行プログラム( calc_runner.php )を動かしてみましょう。

$ php calc_runner.php
Fatal error: Uncaught Exception: Divide by 0. in /Users/your_name/Desktop/code-php/SimpleCalc.php:39
Stack trace:
#0 /Users/your_name/Desktop/code-php/calc_runner.php(9): SimpleCalc->divide(0)
#1 {main}
  thrown in /Users/your_name/Desktop/code-php/SimpleCalc.php on line 39

実行結果を見ると先ほどのように Warning メッセージが出力されていないのがわかります。その代わりに Fatal error: Divide by 0. というメッセージを確認できます。これはPHPの Fatal error (致命的なエラー)が発生したことを意味しており、その原因として Exception がキャッチされなかった( Uncaught Exception )と説明が続きます。またメッセージの後には例外の発生箇所やスタックトレースの出力が確認できます。

ここでは例外をスローする方法として、 Exception クラスと throw キーワードについて取り上げました。以降はここでスローされた例外を適切に処理する方法を解説します。

参考:Exceptionクラス

Exception クラスはPHPに標準で用意されている例外クラスです。 Exception クラスの詳細については PHPマニュアル - Exceptionを参照してください。

まとめ

  • 例外( Exception )とはプログラムの予期せぬ事態を通知する仕組み
  • PHPにはユーザー例外の基底クラスとして Exception クラスが用意されている
  • Exception クラス(および、そのサブクラス)のインスタンスは throw キーワードによって、呼び出し元にスローできる