Request lifecycle
The skeleton wires these stages together. The package overview distinguishes that setup from standalone package usage. Applications using modules also add configuration and provider booting; those stages are not enabled automatically.
You can build a FloCMS site without knowing what happens between the browser's request and your controller. But when something behaves unexpectedly, it helps to know the order of the steps. This page follows one page request from start to finish.
The short version
Browser
→ public/index.php session cookie settings, Composer autoloader
→ config/bootstrap.php .env, error handler, APP_URL, config/config.php
→ maintenance check 503 while `php flo down` is active
→ App::run()
→ Router language, area, controller, action, parameters
→ conf_global.php constants such as ACTIVE_LANG
→ language file lang/<language>.php
→ CSRF check POST, PUT, PATCH and DELETE requests
→ admin checks session freshness, login redirect
→ controller action permission check, then your method
→ view views/<controller>/<action>.html
→ layout templates/<template>/layouts/<area>.html
→ Response sent
API requests take a different path, through public/api.php. See API requests below.
1. The entry point
The web server's document root is public/. Its .htaccess file sends /api/v1/... to api.php, serves existing files (CSS, images, uploads) directly, and sends everything else to index.php.
public/index.php then:
- sets the session cookie to
HttpOnlyandSameSite=Lax, andSecurewhen the request uses HTTPS - loads Composer's autoloader
- starts the session
- loads
config/bootstrap.php
2. Bootstrap
config/bootstrap.php prepares the application:
.envis loaded. If the file is missing, FloCMS shows an error page that says so, with status 500.- The error handler is registered. From here on, every uncaught error or exception ends on an error page.
APP_URLis checked and becomes theSITE_URIconstant, which you use to build links.- Paths and the class aliases of
includes/compat.phpare defined, soConfigworks as well asFloCMS\Core\Config. config/config.phpis loaded. See configuration.
3. Maintenance mode
If php flo down is active, the request stops here with a 503 page, unless the visitor's IP is allowed. Nothing else runs, not even the database connection. See maintenance mode.
4. Routing
App::run() creates the router, which reads the URL from left to right: an optional language, an optional area such as admin, the controller, the action and the parameters. See routing.
Then public/conf_global.php defines constants that views and controllers use, among them ACTIVE_LANG, CURRENT_CONTROLLER, CURRENT_ACTION, IS_ADMIN and VIEWS_PATH. The language file of the active language is loaded, so __() works from now on.
5. CSRF protection
A POST, PUT, PATCH or DELETE request must carry the session's CSRF token, in the _token field or the X-CSRF-TOKEN header. Without a valid token, the request stops with status 419. See sessions and CSRF.
6. Admin checks
For requests under /admin:
- Session freshness. When
auth.user_loaderis configured, the signed-in user's role and status are reloaded from the database, so a suspended user loses access on their next click. See authentication. - Login. Visitors without admin access are redirected to
/admin/users/login/. Signed-in admins who open the login page go to/admin/.
7. The controller action
The router's controller name becomes a class: blog-post and blog_post both become FloCMS\Controllers\BlogPostController. FloCMS then checks, in this order:
- The controller name contains only letters, digits,
_and single hyphens between words, and the action name only letters, digits and_. - The class exists and extends
FloCMS\Core\Controller. - The action is a public, non-static method on your controller or your own base controller, excluding methods declared by
FloCMS\Core\Controllerand magic method names. - The current user has the permission that
$actionPermissionsrequires for it (403 otherwise).
A failed name, class or method check answers 404, and a class that doesn't extend Controller is a 500 error. Then your action runs. See controllers.
Note
The controller's constructor runs before the action is checked. Keep constructors light, and create models on first use, as generated controllers do.
8. View and layout
After the action, FloCMS renders a view:
- the path the action returned, if it returned one
- otherwise
views/<controller>/<prefix><action>.html, for exampleviews/blog/admin_index.html
The values in $this->data become variables in the view. The rendered view is then placed in the layout of the area: templates/<template>/layouts/default.html for site pages, admin.html under /admin. The layout prints it with $data['content']. See views and templates.
9. Errors along the way
An exception at any step goes to the error handler. It writes the error to storage/logs/app.log and shows the matching error page: 404, 403, 500, or a database error page. With APP_DEBUG=true, most errors show a detailed debug page instead. See error pages and logging.
API requests
Requests to /api/v1/... go to public/api.php. It loads the same bootstrap and checks maintenance mode, but then hands the request to the flocms-api kernel:
- no session and no CSRF check by default
- routes come from
api/routes.php, not from the URL convention - a middleware pipeline adds security headers, CORS, the locale and rate limits
- every response, errors included, is JSON