PHPには次の2種類の例外系が存在しますね。
  1. RuntimeException
  2. LogicException
これはどのように使い分けるべきなのかについて
PHPのドキュメント(http://www.php.net/manual/)をベースに調べてみたので共有します。


まずは結論!
  1. RuntimeException系 : 運用で通常発生しうる例外
    発生してもバグとは限らない。通常の例外。
    例) throw new RangeException("規定範囲外の値が入力されました");
  2. LogicException系 : バグ検出のために仕込む例外。
    本来、実運用時には発生しない。発生したらバグ。
    例) throw new LogicException("引数で数値以外を渡さないでください!!");

java にも同名の例外がありますが、java の使い分け方とは全く異なるので java 使いには要注意です。


根拠は次の通り。

(1) php の例外の構成

(インデントは継承関係を表す)
Exception

    RuntimeException                : 実行時にだけ発生するエラー。
        OutOfBoundsException        : キーが範囲外。
        UnexpectedValueException    : 値が期待値外。
        RangeException              : 範囲エラー。
        OverflowException           : オーバーフロー。
        UnderflowException          : アンダーフロー。

        HttpException               : CakePHP で導入される例外。http関連。
            BadRequestException
            InternalErrorException
            など
        CakeException               : CakePHP で導入される例外。CakePHP関連。
            MissingControllerException
            MissingActionException
            など

 LogicException : プログラムのロジックエラー。バグ検出用。 BadFunctionCallException : 関数が未定義。引数なし。 BadMethodCallException : メソッドが未定義。 DomainException : 値が範囲外。 InvalidArgumentException : 引数が不正。 LengthException : 長さが異常。 OutOfRangeException : 値の異常。
php には LogicException と RuntimeException の2体系があります。
まずは RuntimeException を見てみます。


(2) RuntimeException の2つの謎
RuntimeException

実行時にだけ発生するようなエラーの際にスローされます。 Exception thrown if an error which can only be found on runtime occurs.
ここで疑問が2つ。

1つ目は、「実行時にだけ 発生するようなエラー」 とあるが、例外ってそもそも実行時にしか発生しないような。。。php では実行時以外でも発生するのだろうか。。。

2つ目は、Runtime の辞書的な意味は大きく2つ(「実行時」「ライブラリ」が)あるが、「実行時」で間違いないのか?

両者を検証すべく、他の例外のドキュメントをすべて確認してみると、驚くべき記述が見つかりました。


(3) 謎のワード 「コンパイル時」
OutOfBoundsException

値が有効なキーでなかった場合にスローされる例外です。
これは、コンパイル時には検出できないエラーです。

Exception thrown if a value is not a valid key.
This represents errors that cannot be detected at compile time.  
コンパイル時には検出できない!!!??
ということは、コンパイル時に検出できるエラーがありえるのか???
コンパイル時に検出できないから、そもそも例外を使うのではないのか。
なぜ、わざわざこの例外だけ、この記述がなされているのか。

謎が深まりましたが、とりあえず、他のドキュメントも確認してみます。
すると理解のカギとなりうる記述を発見しました。


(4) カギとなるワード 「実行時版」
RangeException

プログラムの実行時に範囲エラーが発生したことを示すときにスローされる例外です。
通常は、アンダーフローやオーバーフロー以外の計算エラーが発生したことを意味します。
これは、実行時版の DomainException です。

Exception thrown to indicate range errors during program execution.
Normally this means there was an arithmetic error other than under/overflow.
This is the runtime version of DomainException.
「実行時版」 という言葉が使われています。
ということは、「実行時版」 ではない DomainException と対比すれば何かわかるかも!
DomainException

定義したデータドメインに値が従わないときにスローされる例外です。

Exception thrown if a value does not adhere to a defined valid data domain.
ドキュメント自体は参考になりませんが、親クラスがRuntimeExceptionではなく、
LogicException であることがカギとなりそうです!


(5) LogicException の存在を知ることが理解のカギ
LogicException

プログラムのロジック内でのエラーを表す例外です。
この類の例外が出た場合は、自分が書いたコードを修正すべきです。

Exception that represents error in the program logic.
This kind of exceptions should directly lead to a fix in your code.
「自分が書いたコードを修正すべき」 !!
つまり、これが発生したら明らかにバグであるということ。
ということは、php の 「例外」 界では、

実行時 = RuntimeException系以外の例外は発生しないはず

という意味で使われているようです。
Runtime の辞書的な意味では 「実行時」 ですね。

つまり、まとめると、こういうことです。


(6) まとめ
  1. RuntimeException系 : 運用で通常発生しうる例外
    発生してもバグとは限らない。通常の例外。
  2. LogicException系 : バグ検出のために仕込む例外。
    本来、実運用時には発生しない。発生したらバグ。

(7) しかし、2点ほど謎が残りました。
  1. OutOfRangeException ではなぜ 「コンパイル時には検出できない」 とあえて明言したのでしょうか。
  2. 「実行時」 を表す原文に 「on runtime」 と紛らわしい表現をなぜ使ったのでしょうか。「at runtime」 のほうが一般的だし、まぎれも少ないのに。


(8) java 使いは要注意

ちなみに、java の例外にも RuntimeException、Exception という2系統がありますが、
catch 必須かどうかという次元の異なる理念が入っているため、
同じ名前でも区分けが全く異なります。java 使いには要注意ですね。
  1. RuntimeException系 : バグ検出のために仕込んだもの + 発生したら正常処理ができえないもの。
  2. Exception系 : 発生したら、呼び出し元で相応の処理を求めるもの。
java + PHP の人にしてみると、バグ検出のために使うのが RuntimeException かどうかで壮絶な混乱が予想されます。