PHP 5.3で追加された例外のうんたらかんたら

PHPマニュアル先生:

例外 をネストできるようになりました。

PHP: 新機能 - Manual

僕:

php 5.3で例外のネストができるようになったってマニュアルに書いてあるけど、具体的になにができるようになったんですか!だれかおしえて!

OGAWA Katsuhiro on Twitter: "php 5.3で例外のネストができるようになったってマニュアルに書いてあるけど、具体的になにができるようになったんですか!だれかおしえて!"

@akky:

コンストラクタに渡すことで前の例外情報を保ちつつ別の例外を投げられるようになった

Akky on Twitter: "@fivestr コンストラクタに渡すことで前の例外情報を保ちつつ別の例外を投げられるようになった"

Javaから来た用語ですかね。Javaでも1.4から導入されました。あると便利ということかと http://bit.ly/acr5r4

Akky on Twitter: "@fivestr @Kiske Javaから来た用語ですかね。Javaでも1.4から導入されました。あると便利ということかと http://bit.ly/acr5r4"

なるほど!PHP 5.3ではExceptionの第3引数に前に発生した例外を渡せるようになり、getPrevious()メソッドで取得できるようになったとのこと。

<?php

try {
  // tryの中にtryを書くことは以前からできた
  try {
    throw new LogicException('ゆどうふ', 28);
  } catch (LogicException $le) {
    throw new Exception('error!', 0, $le);
  }
} catch (Exception $e) {
  $prev = $e->getPrevious();
  echo sprintf('[%s] %s (%s)', get_class($prev), $prev->getMessage(), $prev->getCode());
  #=> [LogicException] ゆどうふ (28)
}

とりあえず一件落着です。akky++
と思ったら、

id:sasezaki:

私の見てるマニュアルには載ってますよ!
http://framework.zend.com/manual/ja/zend.exception.previous.html

PHPとZend Frameworkでの前の例外 - 例えば、PHPを使う

Zend_Exceptionクラスには第3引数があるとのことです。

というわけで、いつものごとくsymfonyの話。やりたいことはちょっと違いますが、sfExceptionが似たようなことをやっています。

<?php

class sfFrontWebController extends sfWebController
{
  public function dispatch()
  {
    try
    {
      // Forwarding requested action...
    }
    catch (sfException $e)
    {
      $e->printStackTrace();
    }
    catch (Exception $e)
    {
      sfException::createFromException($e)->printStackTrace();
    }
  }
}
<?php

class sfException extends Exception
{
  static public function createFromException(Exception $e)
  {
    $exception = new sfException(sprintf('Wrapped %s: %s', get_class($e), $e->getMessage()));
    $exception->setWrappedException($e);
    self::$lastException = $e;

    return $exception;
  }
}

こんな感じで、sfExceptionは他の例外をラッピングするということができます。sfException::printStackTrace()で500エラー画面を返すという処理をしており、例外発生時はsfExceptionでラッピングしてエラーを表示するということを行っています。まあsfExceptionはsymfonyの内部用の例外だと思うので実際のビジネスロジック中で例外のネストがしたいならPHP 5.3を使うか自前で実装するかになりますが。。。

なにはともあれ、akkyさん、sasezakiさん、Kiskeさん、ありがとうございました!