Request Lifecycle
Follow an HTTP request from the front controller to the rendered response.
1. Front controller (public/index.php) #
- Composer autoload + shared application bootstrap via
bootstrap/app.php. $app->boot()registers core services, loads config, and boots modules.Request::capture()snapshots PHP superglobals.- Router is resolved from the container (
$app->make('router')). - Route caching? If
storage/cache/routes.phpexists (generated byvelvet route:cache), it is loaded immediately; otherwiseroutes/web.phpis executed to register routes (and modules can add more duringboot()).
2. Router dispatch #
Router::dispatch()normalizes the HTTP method (including_methodspoofing on POST) and path, then emitsrouter.matchingandrouter.matchedevents.- Route patterns support
{slug}, optional{slug?}, and greedy{asset*}parameters. Named routes are tracked forurl()generation. - The router builds a middleware stack from
config/http.phpglobals + route-specific middleware (added via->middleware(...)).
3. Middleware pipeline #
VelvetCMS\Http\Middleware\Pipeline executes middleware back-to-front:
- Global aliases are configured in
config/http.php(e.g.,'errors' => ErrorHandlingMiddleware::class). - Each middleware receives
(Request $request, callable $next)and returns aResponseor defers to$next($request). - Built-in middleware:
ErrorHandlingMiddlewarecatchesThrowable, delegates to the exception handler, and rethrows inapp.debugmode.VerifyCsrfTokenenforces CSRF tokens on mutating verbs unless a path matches itsexceptpatterns.
4. Controller / handler execution #
- Route handlers can be closures or
[ControllerClass::class, 'method']. Controller dependencies are autowired via the application container. - Whatever the handler returns is coerced into a
Response: strings become HTML, arrays become JSON, everything else is stringified.
5. Response sending #
Response::send()sets the HTTP status, writes headers, and echoes the body. Helpers likeResponse::json(),Response::file(),Response::redirect(), andResponse::methodNotAllowed()simplify common patterns.- Theme rendering is handled in route closures (
$theme->render($page)) so the router itself stays framework-agnostic.
6. Exception handling #
- The front controller wraps dispatch in the shared
ExceptionHandlerInterfaceimplementation (VelvetCMS\Exceptions\Handler). Handler::report()logs errors, triggersexception.reporting, and lets custom reporters short-circuit.Handler::render()firesexception.renderingand falls back to:- Debug mode (
app.debug=true): JSON or HTML with stack traces. - Production:
Response::error('Server Error', 500)or JSON equivalent.
- Debug mode (
- Middleware can also intercept exceptions earlier (e.g., for API-specific formatting) by inserting before
ErrorHandlingMiddleware.
7. Keep it fast in production #
- Run
velvet route:cacheduring deploys to dump the compiled route array and skip parsing/regex compilation on each request. - Pair this with opcode caching (OPcache) and HTTP asset caching headers (see
config/theme.php) for best results.
That’s the entire journey: bootstrap, capture, route, middleware, handler, response. Hooks (router.*, exception.*, module boot) let you customize each segment without touching the core.