Repository navigation
Request Lifecycle
Request Lifecycle Diagram:
When building an application with mouse-php, it helps to understand how a request flows through the system.
An important foundational concept to understand about mouse-php is that it operates as a synchronous API server. Every incoming HTTP request bootstraps the framework, executes the request lifecycle, and completely terminates ("dies") upon completion. This differs fundamentally from asynchronous or event-driven engines like Express.js, where a long-running process persists across multiple requests.
mouse-php's core architecture and recommended design patterns are built around this synchronous lifecycle. Understanding this flow ensures you can take full advantage of a clean, stateless execution environment rather than fighting against it.
When a client hits a mouse-php API endpoint, the application entry point is always ./public_html/index.php. Your web server configuration (e.g., Apache or Nginx) should always rewrite incoming traffic to point to this file.
From there, the initialization sequence begins:
-
index.phpinstantiates a new instance ofMouse_Core. -
The constructor of
Mouse_Coreinitiates the bootstrapping process:-
Loads core configuration variables.
-
Loads defined Web and API route arrays into memory.
-
Sets appropriate CORS headers for the incoming request.
-
-
The
init()method is invoked, triggering the routing engine.
Once the application is bootstrapped, the routing engine takes over. Its primary job is to route the request to the proper resource, or kill the request early if the route is invalid, avoiding unneeded resource allocation and wasted compute cycles.
The engine executes load_routing(), which performs the following steps:
-
Extracts Request URI: Collects request data to determine the incoming path.
-
Determines Route Category: Inspects the first path segment. If the URI starts with
/api, it is processed as an API route; otherwise, it defaults to a Web route. -
Route Matching & Variable Injection: It iterates over the respective route array to find a match.
During route matching, the engine checks for dynamic path elements. For example, if a URI of /api/user/42 matches the defined route /api/user/:id:, the engine extracts this value into the request payload under the vars array as "id" => 42.
Because mouse-php uses standard PHP associative arrays rather than complex Regular Expressions (Regex) for lookup logic, route matching executes at rapid O(1) speeds, even when parsing dynamic parameters.
For a deeper breakdown of route configuration, see the Routing Documentation.
Once a route is confirmed to exist, mouse-php bootstraps the database connection.
This deferred database connection strategy is an intentional optimization: prior to route confirmation, no database interaction is needed. If a request hits an invalid endpoint, the process dies immediately without ever incurring the network latency or overhead of opening a database socket.
Once the route is validated, the database is live, and middleware metadata is attached, the payload moves to the Middleware Engine.
The Middleware Engine determines which middleware modules need to execute for the matched route and manages their output pipeline.
Middleware modules act as generic, reusable guards across endpoints, handling tasks like request validation, rate limiting, or user authentication.
-
Module Output: Every middleware module returns a boolean indicating whether the request should proceed or immediately abort.
-
Data Injection: Modules can inject fresh data (e.g., an authenticated user object or validated payload) directly into the request data pipeline for use inside the controller.
To learn more about constructing custom middleware, check out the Middleware Documentation.
Once all assigned middleware modules pass successfully and inject their respective state, mouse-php initializes the controller.
Using the payload assembled by the routing and middleware engines, mouse-php instantiates the designated controller, passing it:
-
The consolidated request data (including URL variables and middleware state).
-
The primary database object.
-
The SQLite object.
The controller method assigned to the route then executes.
Unlike monolithic frameworks that promote "skinny controllers and fat models," mouse-php uses an Inverted MVC model optimized for its role as a high-speed Data Marshal for decoupled Single Page Applications (SPAs) and frontends:
-
The Controller: Acts as the primary orchestrator. This is where business logic, query composition strategy, response formatting, and JSON payload construction live.
-
The Model: Acts as a lightweight, reusable pipeline to external resources (e.g., database tables, external APIs, or microservices).
┌──────────────────────────────────────────────────────────────┐
│ INVERTED MVC DATA FLOW │
├──────────────────────────────────────────────────────────────┤
│ Client Request │
│ │ │
│ ▼ │
│ [ Controller ] ── (Orchestrates Business Logic & JSON) │
│ │ ▲ │
│ │ │ Fetches Data │
│ ▼ │ │
│ [ Model Pipelines ] ──► (Database / SQLite / External APIs) │
└──────────────────────────────────────────────────────────────┘
By treating models as focused data pipelines rather than heavy domain mappers, controllers can nimbly combine calls across multiple models within a single request without duplicating SQL or query logic.
-
Example: An endpoint needs to return a list of posts along with the profiles of the authors who wrote them. The controller calls a query method on
Posts_Modelto fetch the posts, extracts theauthor_ids, and passes those IDs to an existing method onUser_Model.
By placing data orchestration in the controller and keeping models lightweight, you maintain fast, linear execution without rewriting data fetching logic.
After gathering the necessary data and constructing the JSON response, the controller sends the HTTP response back to the client. The request lifecycle completes, memory is flushed, and the process terminates cleanly.