Request Lifecycle
This document traces the complete lifecycle of an HTTP request handled by Alxarafe, from the entry point (index.php) to the rendered response.
Sequence Diagram
sequenceDiagram
participant Client
participant index.php
participant Dispatcher
participant WebDispatcher
participant Routes
participant Controller
participant ViewTrait
participant Blade
Client->>index.php: HTTP Request
index.php->>Dispatcher: Dispatcher::run()
Note over Dispatcher: initializeConstants()<br/>ALX_PATH, APP_PATH,<br/>BASE_PATH, BASE_URL
Dispatcher->>Dispatcher: Trans::initialize()
alt URL contains /index.php/api/
Dispatcher->>Dispatcher: ApiDispatcher::run()
Note over Dispatcher: API lifecycle (see API docs)
else Standard web request
Dispatcher->>WebDispatcher: run(module, controller, method)
end
WebDispatcher->>WebDispatcher: Debug::initialize()
WebDispatcher->>Routes: Routes::getAllRoutes()
Note over Routes: Scans Modules\\<br/>namespaces for<br/>*Controller.php files
Routes-->>WebDispatcher: route map
WebDispatcher->>WebDispatcher: Resolve className from route
WebDispatcher->>WebDispatcher: Load config, theme, language
WebDispatcher->>WebDispatcher: Check Auth user preferences
WebDispatcher->>Controller: new ControllerClass()
Note over Controller: GenericController::__construct()<br/>→ Build menus<br/>→ Boot traits (initTraitName)
Note over Controller: ViewController::__construct()<br/>→ Load config<br/>→ Register template paths<br/>→ Set language
Note over Controller: Controller::__construct()<br/>→ Auth check (isLogged)<br/>→ Module activation check<br/>→ Authorization check (can)
WebDispatcher->>Controller: setTemplatesPath(paths[])
WebDispatcher->>Controller: $controller->index()
Controller->>Controller: executeAction()
Note over Controller: Resolve action from<br/>$_GET['action'] or $_POST['action']<br/>Build method name: do{Action}
Controller->>Controller: beforeAction()
Controller->>Controller: doAction()
Controller->>Controller: afterAction()
Note over Controller: afterAction() calls<br/>Messages::getMessages()<br/>then $this->render()
Controller->>ViewTrait: render()
ViewTrait->>Blade: Compile & render template
Blade-->>Client: HTML ResponsePhase 1: Bootstrap (index.php)
The web server directs all requests to public/index.php. A typical entry point:
<?php
// public/index.php
require_once __DIR__ . '/../vendor/autoload.php';
define('BASE_PATH', __DIR__);
use Alxarafe\Tools\Dispatcher;
Dispatcher::run();Alternatively, applications may use WebDispatcher::dispatch() directly for more control:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
define('BASE_PATH', __DIR__);
use Alxarafe\Tools\Dispatcher\WebDispatcher;
WebDispatcher::dispatch('MyModule', 'Home', 'index');Phase 2: Initialization (Dispatcher::run())
Dispatcher::run() performs two initialization steps:
2a. Constant Definition
// Dispatcher::initializeConstants()
ALX_PATH = realpath(__DIR__ . '/../../..') // Framework root
APP_PATH = realpath(ALX_PATH . '/../../..') // Application root
BASE_PATH = APP_PATH . '/public' // Document root
BASE_URL = Functions::getUrl() // Auto-detected URL2b. Translation System
Trans::initialize(); // Loads YAML language files from src/Lang/2c. Routing Fork
The dispatcher inspects $_SERVER['PHP_SELF'] for the pattern /index.php/api/:
- API requests →
ApiDispatcher::run($controllerPath)→ JSON response - Web requests →
WebDispatcher::run($module, $controller, $method)→ HTML response
The module, controller and method are extracted from $_GET parameters:
moduledefaults to'Admin'controllerdefaults to'Info'methoddefaults to'index'
Phase 3: Route Resolution (WebDispatcher::run())
3a. Debug Initialization
Debug::initialize(); // Sets up DebugBar if in debug mode3b. Route Discovery
$routes = Routes::getAllRoutes();
$endpoint = $routes['Controller'][$module][$controller];
// e.g. "Modules\Admin\Controller\HomeController|/path/to/HomeController.php"Routes::getAllRoutes() scans two namespace roots:
| Root | Namespace | Always Active |
|---|---|---|
src/Modules/ | Modules\ | Yes |
APP_PATH/Modules/ | Modules\ | Checked via Setting table |
For each module directory, it discovers:
Controller/*Controller.php→ Web controllersApi/*Controller.php→ API controllersMigrations/*.php→ Database migrationsSeeders/*.php→ Data seedersModel/*.php→ Eloquent models
3c. Friendly URL Matching
Before falling back to $_GET parameters, WebDispatcher::dispatch() first attempts Router::match() against the request URI for friendly URLs.
3d. Theme & Language Resolution
The theme and language are resolved in priority order:
- Cookie (
alx_theme,alx_lang) — highest priority - Authenticated user preferences (
Auth::$user->getTheme(),Auth::$user->language) - Config file (
config.json → main.theme,main.language) - Default (
'default'theme,'en'language)
Phase 4: Controller Instantiation
The resolved class is instantiated. The constructor chain runs bottom-up through the inheritance hierarchy:
4a. GenericController::__construct()
- Action resolution:
$action = $action ?? $_POST['action'] ?? $_GET['action'] ?? 'index' - Menu building:
ModuleManager::getArrayMenu()for top menu,MenuManager::get('admin_sidebar')for sidebar - Back URL: Auto-set if action ≠
'index' - Trait boot: For each trait, call
init{TraitName}()if it exists
4b. ViewController::__construct()
- Config load:
Config::getConfig() - Template path registration: App templates → Theme templates → Framework templates
- Language init:
Trans::setLang() - Variable injection:
$me= controller instance,main_menu,user_menu
4c. Controller::__construct()
- Authentication:
Auth::isLogged()— redirects to login if not - Module activation:
MenuManager::isModuleEnabled()— blocks disabled modules - Authorization:
Auth::$user->can($action, $controller, $module)— checks permissions - Username: Sets
$this->usernamefrom authenticated user
4d. Template Path Setup
After instantiation, WebDispatcher sets the template search order:
$templates_path = [
APP_PATH . '/templates/themes/{theme}/', // Theme override (App)
ALX_PATH . '/templates/themes/{theme}/', // Theme override (Package)
APP_PATH . '/Modules/{Module}/templates/', // Module templates (App)
ALX_PATH . '/src/Modules/{Module}/Templates/', // Module templates (Package)
APP_PATH . '/templates/', // App general templates
ALX_PATH . '/templates/', // Framework default templates
];Phase 5: Action Execution
5a. Method Call
WebDispatcher calls $controller->index() (or the resolved method).
5b. GenericController::index() → executeAction()
- Permission re-check for the specific action
- Method resolution:
'do' . ucfirst(Str::camel($this->action))— e.g.,action='create'→doCreate() - Hook chain:
beforeAction()— override for pre-processingdoAction()— the actual business logicafterAction()— post-processing and rendering
5c. Return Convention
Each method in the chain returns bool. If any returns false, the chain short-circuits:
return $this->beforeAction()
&& $this->$actionMethod()
&& $this->afterAction();Phase 6: Rendering
6a. ViewController::afterAction()
public function afterAction(): bool
{
$this->alerts = Messages::getMessages();
echo $this->render();
return true;
}6b. Template Resolution
ViewTrait::render() resolves the Blade template name from the controller:
- Convention:
page/{controller_name}(lowercase, snake_case) - Example:
HomeController→page/home
6c. Blade Compilation
The BladeContainer compiles and renders the template with all injected variables ($me, $main_menu, $user_menu, $alerts, etc.).
Phase 7: Error Handling
The entire dispatch is wrapped in a try/catch:
- First failure → Redirect to
ErrorController::url()with message and trace - Second failure (anti-loop guard) → Render raw HTML error page directly
- Emergency fallback →
http_response_code(500)with minimal styled error
Summary Table
| Phase | Class | Key Method |
|---|---|---|
| Bootstrap | index.php | Dispatcher::run() |
| Init | Dispatcher | initializeConstants(), Trans::initialize() |
| Route | WebDispatcher | run(), Routes::getAllRoutes() |
| Instantiate | Controller hierarchy | __construct() chain |
| Execute | GenericController | executeAction() → beforeAction() → doAction() → afterAction() |
| Render | ViewController / ViewTrait | afterAction() → render() |
| Error | WebDispatcher | dieWithMessage() → ErrorController |