Slimでエラーを扱えるようになるエラーハンドラ
マイクロフレームワークであるSlimを紹介するこの連載も、いよいよ最終回です。最終回のテーマは、エラーハンドラです。そのエラーハンドラとは何かから話を始めていきましょう。
エラーが発生した時の画面
まず、図1を見てください。
これは、第6回で紹介したサンプルのうち、以下のURLでの処理中にコーディングミスを行って、エラーを発生させている画面です。
- http://localhost/firstslim/src/public/no6/helloNatsume
具体的には、リスト5のhelloNatsume()メソッド中のコンテナからTwigインスタンスを取得しているコードにおいて、以下のようにインスタンス名に間違った記述を行っています。
$view = $this->container->get("vie");
これは、もちろん間違ったコードなので、エラーとなります。その画面が図1です。見て分かるように、図1というのは、PHPのエラー内容がそのままブラウザ上に表示された画面です。ただし、これはXAMPPを前提とした画面であり、php.iniの設定によっては図1の画面すら表示されず、単に500番エラーがブラウザに表示されてしまう実行環境もあります。いずれにせよ、この状態は、アプリケーション内で発生したエラーに対して、Slimは何も関与していないことを表します。
Slimにエラーを処理させる
このように、PHPエラーや例外に対してSlimが関与しない状態ではなく、Slimに含まれているエラーハンドラ機能を利用することで、エラー処理をSlimに任せることもできます。そのように設定した場合(設定方法は後述します)、図1と同じエラーが発生した時の画面は、図2のように変わります。
Trace部分に表示されている内容は、図1の内容と同じですが、全体としてよりみやすいものとなっています。さらに、エラーハンドラ設定を変更することで、同じエラーでも図3のような画面を表示させられます。
図2ではエラー内容が表示されるため、コーディング中は便利ですが、本運用環境には不向きです。むしろ、図3の方が本運用環境には向いています。こういった切り替えも簡単に可能であり、さらに本運用環境用のエラー画面にカスタマイズすることも可能です。
これが、Slimのエラーハンドラの概要であり、本運用を前提としたアプリケーションでは、エラーハンドラの利用は必須と言えます。
Slimのエラーハンドラはエラーミドルウェア
概論はここまでにして、実際にエラーハンドラの設定方法を紹介していきましょう。
Slimのバージョン4からはミドルウェアとして設定
図3の画面は、実はこの連載において初出ではありません。第6回の図1で登場しています。つまり、第6回の段階ではエラーハンドラが設定されていることになりますが、そのような設定をした覚えはありません。
種明かしをすると、これはSlimのバージョンが違うためです。第6回を執筆した時点ではSlimのバージョンは3系列でした。一方、第7回で紹介したように、現在Slimのバージョンは4系列です。
Slimがバージョン3から4にアップデートされた時点で、変更になった内容の1つがこのエラーハンドラです。バージョン3では、エラーハンドラはSlimのコアな処理内容に含まれており、デフォルトでエラーハンドラが実行されるようになっていました。
一方、バージョン4では、このエラーハンドラをコア機能から切り離し、前回紹介したミドルウェアとして実装することになりました。これがエラーミドルウェアです。エラーミドルウェアとしてエラーハンドラを実装することで、より柔軟なエラーハンドラ設定を行えるようになった一方で、エラーハンドラを有効化するコードを別に記述しなければならなくなりました。これが、今回のエラー表示の違いの種明かしです。
エラーミドルウェアの設定
では、実際にエラーミドルウェアを設定していきましょう。といっても、実に簡単です。index.phpの$appをcreate()しているコードと、setBasePath()を実行しているコードの間にリスト1の(1)と(2)の2行を追記してください。
〜省略〜 $app = AppFactory::create(); $app->addRoutingMiddleware(); // (1) $errorMiddleware = $app->addErrorMiddleware(true, true, true); // (2) $app->setBasePath("/firstslim/src/public"); 〜省略〜
Slimのエラーミドルウェアクラスというのは、\Slim\Middleware\ErrorMiddlewareです。また、エラーハンドラというこのミドルウェアの特性を考えたら、特定のルーティングではなく、アプリケーション全体へ登録するものです。となると、前回の最後に紹介したアプリケーション全体にミドルウェアを登録する方法が該当し、Appインスタンスである$appのadd()メソッドを使ってミドルウェアを登録する以下のコードを、index.phpに記述するのが本来の姿と言えます。
$app->add(new ErrorMiddleware(…));
しかし、エラーミドルウェアの登録は、常に行う処理なので、Appクラスに専用のメソッドの形で用意されています。それが(2)で実行しているaddErrorMiddleware()メソッドです。このメソッドの戻り値は、ErrorMiddlewareインスタンスそのものです。それを、(2)では変数$errorMiddlewareとして受け取っています。$errorMiddlewareは、のちに利用します。
このメソッドの引数は、以下の3つで全てbool型なので、true/falseで指定します。
- $displayErrorDetails:trueならば、エラーの詳細をエラー画面に表示します。
- $logErrors:trueならば、サーバ内のログにエラー詳細を出力します。
- $logErrorDetails:trueならば、発生した例外が投げ直しの場合、元となる例外内容もログとして出力します。
1の$displayErrorDetailsについて少し補足すると、前節で紹介した図2と図3の違いは、実はこの引数のtrue/falseの切り替えで起こります。trueの場合が図2であり、falseの場合が図3です。この引数の値は、開発環境と本運用環境でエラー表示を切り替えるのに便利です。
ルーティングもミドルウェアとなったバージョン4
このように、Appインスタンスに対してエラーミドルウェアを適切な引数でもって登録すること、つまりリスト1の(2)の1行の記述で、エラーハンドラが有効になります。
では、リスト1の(1)は、どのような処理なのでしょうか。これは、addRoutingMiddleware()というメソッド名から想像できるように、ルーティングミドルウェアを登録している処理です。
実は、ここもSlimのバージョン4で大きく変わったところで、Slimはルーティング処理そのものもミドルウェアとして実装されています。そうすることで、ルーティング処理が実行されるタイミングを自由に決められるようになりました。ただ、その自由と引き換えに、エラーミドルウェアのような他のミドルウェアと組み合わせる場合は、その順番を考えなければならなくなりました。
エラー処理は、全ての処理の最後で行わないといけません。なので、エラーミドルウェアの登録よりも前にルーティングミドルウェアを登録しておく必要があるのです。(1)で先にルーティングミドルウェアを登録しているのはそういった意味があります。