Routing
Overview
In Pragma CMS, all HTTP requests are intercepted by a single entry point which passes them to the Core Router (router.php).
The Router integrates multiple elements (security, multilingualism, request parsing, and route matching to include the correct file). Here is the exact sequence of the routing lifecycle, broken down into its logical phases:
1. Security & Session Bootstrap
Before processing any content, the router secures the request and initializes sessions:
- CSRF Protection: It generates a unique and secure CSRF token if one does not already exist in the session.
- HTTP Security Headers: It configures strict HTTP security headers:
- Generates a unique cryptographic nonce used to sign inline scripts safely (
$GLOBALS['csp_nonce']). - Sets policies like
Content-Security-Policy (CSP),X-Frame-Options, etc.
- Generates a unique cryptographic nonce used to sign inline scripts safely (
- HTML Page Caching: Enforces cache-control headers (
no-cache, must-revalidate) to handle browser caching behavior properly. - Admin Auto-Login: It handles the automatic login process ("Remember Me" cookie functionality) for the administration panel.
2. Request Parsing & Redirections
The router analyzes the incoming request and checks for immediate routing overrides:
- Request Parsing: It analyzes the HTTP request by retrieving the full URI, extracting the relative path, and identifying the HTTP method used (GET, POST, etc.).
- Redirections: It checks the database and handles HTTP redirections (Exact, Prefix, or Regex matches) if they have been defined by the user in the Admin interface.
3. Multilingual Management
The router completely bootstraps the multilingual context:
- Retrieves the supported languages and the default language from the database.
- Extracts the language code directly from the URL.
- Handles exceptions (such as
/api,/uploads, etc.) to ensure they do not require a language code in the URL. - Retrieves the active language ID needed for database translations.
- Loads the static PHP UI translations for the defined languages from the server's
lang/directories (en.php,fr.php, etc.).
4. System State & Maintenance
- System Notifications: It handles and registers system notifications specifically for logged-in administrators (e.g., missing extensions, available updates).
- Maintenance Mode: It handles the presence (or absence) of the maintenance page, automatically bypassing it for API calls or logged-in administrators.
5. The Route Matching Engine
This is the core of the router. It loads the routing logic from the cache file (automatically generated by the "Routes" page in the admin interface). It then iterates directly through these cached routes, which are already translated, performing the following steps for each:
- Regex Conversion: Converts the route pattern into a regular expression (e.g.,
'blog/{slug}'becomes'#^blog/([^/]+)$#'). - Comparison & Method Check: Compares the current URL against the regular expression and verifies if the current HTTP method is allowed.
- Parameter Extraction: Extracts the URL parameters if present.
- Content Validation: Validates the content before confirming the route (this prevents false positives when multiple
route_patternhave the same number of placeholders). To do this, it checks the database to see if the URL segments have been processed in theroute_segmentstable, and verifies if the slug actually exists for this specific content type via theContentTypeManager. It then retrieves themain_content_type_handle, which is highly useful later in a page/controller. - Permissions: Stores the permission associated with the page (retrieved from the route cache) directly into the Page object (
$page->permission). - Current Route Object: Stores ALL the current route information into
$page->currentRoute(including thehandle,main_content_type_handle, and URL parameters). - Global Variables: Adds the extracted URL parameters into the
$_GETsuperglobal, making them readily available for pages/controllers (e.g., to retrieve a slug). - File Inclusion: Includes the associated PHP controller file using the
resolveCascadingPath()function. This function allows path resolution by searching first in the site's directory, and then falling back to the CMS core directory (Override System). - 404 Fallback: If the loop finishes and no route is found, it safely displays a 404 error page.
Developer API: The $page->currentRoute Object
When your controller or template is finally loaded, the Router has already populated the global $page object with everything you need to know about the current request.
/**
* Example content of $page->currentRoute for the URL: /fr/blog/tech/my-post
*/
array(3) {
["handle"] => string(19) "front.articles.show"
["main_content_type_handle"] => string(7) "article"
["params"] => array(2) {
["category"] => string(4) "tech"
["slug"] => string(7) "my-post"
}
}
Accessing Route Information
Because the router injects extracted route parameters into $_GET, you can safely retrieve them natively in your controllers:
// Retrieve the slug parsed by the router
$currentSlug = $_GET['slug'] ?? null;
// Check the required permission set by the router
$requiredPermission = $page->permission;