今日もまた踏みました

非定期更新:主に何とも言えない事態にあった際に更新しています

PHP の try...catch で Exception がキャッチされない事案が発生

とりあえず結論を知りたいという技術者の方へ

とりあえず

catch (Exception $e)

catch (¥Exception $e)

に変更してリトライしてみてください。
それでもダメな場合は、エラーの内容を確認してみてください

PHP は throw した例外以外は catch しません

例えば 0 の除算とか… オブジェクトが null でしたとかは catch しないです
そちらの場合は、 set_error_handler を使う必要があります

まずは大丈夫なパターンから

このパターンは問題なくキャッチされる

<?php
class TestException extends Exception { }

class Test
{
  public function goTest()
  {
    try
    {
      echo "### Start ###¥n";
      throw new TestException('Test Exception!');
      echo "### End ###¥n";
    }
    catch (Exception $e)
    {
      echo "### Catch ###¥n";
      echo $e->getMessage() . "¥n";
    }
  }
}

$test = new Test();
$test->goTest();

 実行結果

 ### Start ###
### Catch ###
Test Exception!

正しくキャッチされている

似ているけどキャッチされないパターン

上記のソースに namespace を付けるとキャッチされなくなる

<?php namespace sample;
class TestException extends ¥Exception { }

class Test
{
  public function goTest()
  {
    try
    {
      echo "### Start ###¥n";
      throw new TestException('Test Exception!');
      echo "### End ###¥n";
    }
    catch (Exception $e)
    {
      echo "### Catch ###¥n";
      echo $e->getMessage() . "¥n";
    }
  }
}

$test = new Test();
$test->goTest();

 実行結果

### Start ###
PHP Fatal error:  Uncaught exception 'sample¥TestException' with message 'Test Exception!' in test.php:11
Stack trace:
#0 test.php(23): sample¥Test->goTest()
#1 {main}
  thrown in test.php on line 11

とまあ、キャッチされない

原因

当たり前は当たり前なんだけど…

catch (Exception $e)

と記載すると、 catch は sample¥Exception で待ち構えているため、 ¥Exception を継承した sample¥TestException はキャッチしない
なので namespace を付けた場合は、「 catch (¥Exception $e) 」としておくか、 use で Exception を宣言しておく必要がある様だ
他の言語に慣れていると、 Exception で全部キャッチできそうな気になるので気を付けておきたい
最も実害が無いので、常に ¥Exception にしておいても良いかも知れない