エラーハンドリングの実装例
Naifyのエラーハンドリングの実装例を紹介します。Router層の想定エラーをErrorControllerへ流し、予期しない例外はApplication層で最終的に受けます。
このページでは追加する処理を紹介します。ファイル配置と公開入口、BaseController、NaifyViewの初期化とgetView()を先に用意します。Controllerとテンプレートを追加したら、対応するURLを routes/routes.php に登録します。
ルートの書き方
$router->error() にエラー用Controllerを登録します。個別コードと共通ハンドラを分けることもできます。
use Naify\Router\Router;
return static function (Router $router): void
{
$to = $router->createRouteFactory('App\\Controllers\\');
$router->any('/', $to('IndexController::index'));
$router->error([404], $to('ErrorController::notFound'));
$router->error('*', $to('ErrorController::index'));
};
ErrorController
Router層で発生した RouteException は RequestContext から取得できます。HTTPステータスを設定し、Viewへ値を渡します。
namespace App\Controllers;
final class ErrorController extends BaseController
{
public function indexAction(): void
{
$error = $this->context->getRoutingError();
$code = $error?->getStatusCode() ?? 500;
$message = $error?->getMessage() ?? 'Internal Server Error';
http_response_code($code);
$view = $this->getView();
$view->assign('code', $code);
$view->assign('message', $message);
$view->setTemplate('error.html');
}
public function notFoundAction(): void
{
http_response_code(404);
$view = $this->getView();
$view->assign('code', 404);
$view->assign('message', 'ページが見つかりません');
$view->setTemplate('error.html');
}
}
Viewテンプレート
エラーページも通常のNaifyView Nativeテンプレートとして扱います。
<h1>{{ code }}</h1>
<p>{{ message }}</p>
<p><a href="/">トップへ戻る</a></p>
Application層の最終catch
想定外の例外はブートストラップ側で最終的に受け、ログへ残します。本番環境ではスタックトレースを画面へ出しません。
// SampleAppBootstrap.php のApp生成以降を置き換える
// $config は Naify::createConfig() で設定済み
try {
$app = Naify::createWebApp($config);
$app->loadRoute('routes/routes.php');
$app->run();
} catch (Throwable $e) {
error_log($e->getMessage() . PHP_EOL . $e->getTraceAsString());
http_response_code(500);
echo '<h1>500 Internal Server Error</h1>';
}