WebエンジニアのLoL日記

LoLをプレイしたりLJLの試合を見たりするのが好きなエンジニア。LoLのイベントやパッチノートなど気になった点を記事にしたり、LJLについの記事をかいたりしています。某社でWeb系のエンジニアとして働いているので、技術系の記事もたまに書きます。コンタクトを取りたい場合はtwitterまで。

PHP7の例外(Exception)の関係、正しく例外を使いましょう。

f:id:yoshiki_utakata:20181004212834j:plain

PHP7の例外のうちよく使う例外と構造は以下の通りです。

  • Thorwable
    • Error
    • Exception
      • RuntimeException
      • LogicException

もっと詳細な図は以下の記事を見るとわかりやすいです。

qiita.com

Thorowable

Throwableはすべての例外の基底クラスで、PHP7から新しくできました。PHP5ではキャッチできなかった例外もキャッチできます。ただし、Throwableをtry-catchでキャッチするのはあまり良いとは言えません。構文エラーやロジックのエラーなど、本来コード修正を入れるべきエラーもキャッチしてしまうからです。

ThrowableはErrorとExceptionに別れます。

Error

PHP5まではキャッチできなかったタイプの例外です。ParseErrorやTypeErrorなどがErrorに含まれます。ErrorはPHPの文法エラー等によって起こるものなので、基本的にはtry-catchでキャッチすべきではありません。「コードの書き方が間違っている」時に発生する例外ですので、キャッチするのではなくコードを修正してください。

Exception

PHP5まででもキャッチできた例外です。Exceptionの子クラスには以下のようなクラスがあります。

  • RuntimeException
  • LogicException

大きく分けて「RuntimeException」と「RuntimeException以外」があると思っていれば十分で、RuntimeException以外でよく使うのはLogicExceptionです。

基本的にはExceptionも catch (Exception $e) などとするべきではありません。キャッチすべき例外はRuntimeExceptionとその子クラスで、それ以外の例外は「コードが間違っている」例外になるので、コードを修正するべきなのです。

RuntimeException

「データベースに接続しようとしたけどホストが落ちていてつながらなかった」「ユーザーからの入力値が不正な値だった」といった実行時に発生する例外がRuntimeExceptionです。コードが正常でも発生する可能性があり、実行時になって初めて発生するかどうかが決まる例外で、キャッチして何らかの例外処理をすることが期待されています。

例えば、

  • RuntimeExceptionをキャッチして「ただいまシステムエラーが起きています。復旧までしばらくお待ち下さい」という表示を出す。
  • RuntimeExceptionを継承したクラスMaintenanceExceptionを実装し、MaintenanceExceptionをキャッチした場合は「ただいまメンテナンス中です」の表示を出す。
  • PHPに標準で実装されているUnexpectedValueException(RuntimeExceptionを継承している)をキャッチし、「正しいメールアドレスを入力してください」などとユーザーにメッセージを出す。

などという使い方をします。RuntimeException以外をキャッチしているコードは何かが間違っていると感上げて良いです。

LogicException

Exceptionの子クラスで、「ロジックが間違っている」ことを表す例外です。例えば「ユーザーIDが正の整数で渡されることが期待されているのに負の値が来た」などの例外です。この場合は LogicException を継承した InvalidArgumentException を利用するのが良いでしょう。本来負の値が来るはずが無い箇所で負の値が届いているので、コードが誤っているということになります。直ちにコードを修正しましょう。

まとめ

  • RuntimeExceptionはキャッチするべき例外。
  • それ以外はキャッチするべきではない例外。コードが間違っているので修正しましょう。
  • キャッチする時だけでなく、スローする時も例外を正しく使いましょう。