developmentモードでスクリプトエラーが起こった場合、
以下の様な画面が表示される。
Mojolicious側でアプリの全体的なエラーをキャッチして、
このようなエラー画面を表示させている。
内部では、around_dispatchというフックを使って処理している。
独自にアプリ全体のエラーをキャッチして、
何かしらの処理したい場合も around_dispatch を使う。
(強力なフックなので気軽に使うべきではないと、
ドキュメントで注意されているのでちょっとこわい)
例えば、アプリのエラーメッセージに、
「SYSTEM ERROR!!」というプレフィクスを付けたいとすると、
以下のような設定になる。
app->hook(around_dispatch => sub {
my ($next, $c) = @_;
eval { $next->(); 1; };
# アプリにエラーが起こった場合
if ($@) {
$c->app->log->fatal('SYSTEM ERROR!!: '.$@);
die $@;
}
});
これで、ログにエラーメッセージを出しつつ、
通常通りのエラー画面がブラウザに表示されるようになる。
around_dispatchについて
デフォルトで around_dispatch で設定されている処理は以下のもの。
- エラー処理(Mojolicious::_exception)
- ディスパッチ処理(Mojolicious::dispatch)
前節の設定を行うと、この2つの処理の間に入ることになる。
つまり、
エラー処理
↓
独自エラー処理
↓
ディスパッチ処理
の順番で、実行されていく。
各処理中に「$next->()」を呼び出すことにより、
次の処理を実行する。
前節の設定で「$next->()」という記述があったが、
これは「ディスパッチ処理の実行」を意味していた。
また、Mojolicious::_exceptionの内容は以下のようになっている。
sub _exception {
my ($next, $c) = @_;
local $SIG{__DIE__}
= sub { ref $_[0] ? CORE::die($_[0]) : Mojo::Exception->throw(@_) };
$c->render_exception($@) unless eval { $next->(); 1 };
}
_exceptionの中でも、「$next->()」が記述されている。
これは、前節で設定した処理を実行していることになる。
このように、「$next->()」を呼び出すことによって、
連続的に次の処理を呼び出す形になっている。
「$next->()」をしなかった場合は、処理が止まってしまうので注意。
結構重要な処理がこのフックで呼ばれているので、
触らずに済むなら触らないようにしたい。