Docs LATEST

Application Lifecycle

How requests flow through the framework.

Architecture

Understanding the request lifecycle helps you know where to hook in custom logic and debug issues.

Entry Points #

Entry File Purpose
HTTP public/index.php Web requests
CLI velvet Console commands
Tests tests/bootstrap.php PHPUnit bootstrap

HTTP Request Flow #

Request → Tenancy → Bootstrap → Providers → Assets → Routes → Middleware → Controller → Response

1. Capture Request #

The request arrives at public/index.php. A Request object is created from PHP globals.

2. Resolve Tenancy #

If tenancy is enabled, the tenant is resolved from the host, path, or custom resolver. This sets up tenant-scoped paths for the rest of the request.

3. Bootstrap Application #

bootstrap/app.php creates the Application container and registers core bindings.

4. Boot Providers #

CoreServiceProvider registers framework services. Then module service providers are registered and booted in dependency order.

Events fired:

  • app.booting - before providers boot
  • app.booted - after all providers boot

5. Serve Assets #

The AssetServer checks if the request matches /assets/*. If so, it serves the static file and exits early.

6. Register Routes #

If routes aren't cached, route files are loaded. Module routes are registered via their service providers.

7. Dispatch Through Middleware #

The request passes through global middleware, then route-specific middleware.

Events fired:

  • router.matching - when matching starts
  • router.matched - when a route matches

8. Execute Controller #

The matched route's handler runs. Controllers are resolved from the container with dependencies injected.

9. Return Response #

The controller returns a Response (or a value that's converted to one). The response is sent to the client.

CLI Flow #

Command → Tenancy → Bootstrap → Register Commands → Execute

1. Parse Command #

The velvet script parses the command name and arguments.

2. Resolve Tenancy #

If TENANCY_TENANT is set, that tenant context is used. Otherwise, the default tenant applies.

3. Bootstrap Application #

The app bootstraps if possible. Some commands (like install) run without full bootstrap.

4. Register Commands #

Built-in commands register first. Then the commands.registering event fires, allowing modules to add their commands.

5. Execute Command #

The command runs and returns an exit code.

Key Hooks #

Where to add your logic:

Need Where
Early initialization app.booting event
After app ready app.booted event
Before route matching router.matching event
After route matched router.matched event
Transform request Global middleware
Auth/validation Route middleware
Business logic Controllers/Services