Bootstrap
require StaticPHP\Core\Bootstrap::FILE is the whole of starting the framework. This page
is what that one line sets in motion, in order.
Bootstrap::FILE and Bootstrap::AUTOLOAD, the path constants they resolve, and why the
entry point is a constant rather than a run() method are covered in
the front controller. The short version
is that Bootstrap::AUTOLOAD brings up the path constants and the application autoloader
and nothing else, while Bootstrap::FILE - the file this page describes - brings up
everything.
The boot sequence
Section titled “The boot sequence”Requiring Bootstrap::FILE runs the following top to bottom. Each step is listed with the
reason it sits where it does, because the order is the interesting part - most of these
steps depend on the one before it having already run.
-
$microtime = microtime(true). First statement in the file, at global scope. Every number Timers reports is measured from here. -
require_once dirname(__FILE__) . '/Autoload.php'. DefinesSP_PATH,APP_PATH,APP_MODULES_PATH,BASE_PATHandVENDOR_PATH, throws aRuntimeExceptionif the front controller never definedPUBLIC_PATH, and registers the application autoloader. Nothing below can name an application file until this has run. -
Request::populateFromCli(). Under the cli SAPI this rewrites$_GET,$_POST,$_REQUESTand several$_SERVERkeys fromargv; under any other SAPI it returns immediately. It must precede step 4 because the application’sConfig.phpbinds$config['request_uri']and friends to$_SERVERentries by reference - rewriting the superglobals afterwards would leave the configuration describing a request that was never made. See Request. -
Config::load(['Config', 'Routing']). ReadsAPP_PATH/Config/Config.phpandAPP_PATH/Config/Routing.phpintoConfig::$items. -
The client address is resolved, but only when the application left it alone:
<?phpif (Config::get('client_ip', null) === null) {Config::$items['client_ip'] = Router::clientIp();}It sits here because the configuration governing it -
trust_proxy_headers,trusted_proxy_hops- has only just been read, and because everything below may want an address to log against.nullmeans “work it out”, the waybase_urldoes; anything the application assigned is kept, including the 1.x= & $_SERVER['REMOTE_ADDR']binding. See proxy headers. -
Debug is decided, and
nowanddate_timeare written.<?phpConfig::$items['now'] = time();Config::$items['date_time'] = new ExtendedDateTime();Config::$items['debug'] = Config::resolveDebug();resolveDebug()returnstruefor a truthy$config['debug'], and otherwise calls$config['debug_check']- the application’s owncallable(): bool- and requires a stricttrue. It fails closed. The rules in full are on the Config API.error_reportingis then set toE_ALLwhen debug is on andE_ALL & ~E_DEPRECATEDwhen it is off, anddisplay_errorsto(int) Config::$items['debug']- the value computed just above, not the one the config file assigned. Every later step readsConfig::$items['debug'], so nothing that cares about debug mode can run before this, anddebug_checkin particular runs before sessions, the database and routing exist. -
$config['autoload_configs']is loaded. Each entry is split on/and read right to left: one part is a file inAPP_PATH/Config, two parts aremodule/file, three areproject/module/file. Entries that are not strings are skipped. -
The error handlers are registered.
Load::helper(['ErrorHandlers'], 'Core', 'staticphp')requiressrc/Core/Helpers/ErrorHandlers.php, then:<?phpset_error_handler('sp_error_handler', (!empty(Config::$items['debug']) ? E_ALL : E_ALL & ~E_DEPRECATED));set_exception_handler('sp_exception_handler');Everything above this line runs under PHP’s default handling; a failure in the application’s
Config.phpwill not render through the framework’s error pages. See errors. -
The twig environment is built, unless
$config['disable_twig'] === trueor\Twig\Environmentdoes not exist. The check isclass_exists()rather than a probe for a file underVENDOR_PATH, so it survives twig moving its own internals around. Details below. -
$config['autoload_helpers']is loaded, using the same one/two/three part naming as step 7, throughLoad::helper(). -
Router::init(). Parses the url, finds a controller and calls it. Everything the request does happens inside this call. See the router.
There is no step after Router::init(). Control returns to the front controller, which by
convention has nothing left to do.
What the bootstrap writes back into the configuration
Section titled “What the bootstrap writes back into the configuration”| Key | Value |
|---|---|
client_ip |
Router::clientIp(), only when the application left the key null |
now |
time() at boot |
date_time |
a StaticPHP\Utils\Models\ExtendedDateTime instance |
debug |
the computed boolean from step 6 |
view_loader |
\Twig\Loader\FilesystemLoader, only when twig is in use |
view_engine |
\Twig\Environment, only when twig is in use |
Router::splitSegments() later defines the BASE_URL constant as well.
The twig environment
Section titled “The twig environment”When it is built, the loader searches three directories in this order:
<?php
new \Twig\Loader\FilesystemLoader([ APP_MODULES_PATH, APP_PATH, SP_PATH . '/Core/Views',]);The environment gets cache => APP_PATH . '/Cache/Views/', or false when debug is on,
and debug => Config::get('debug').
Registered on it:
| Name | Kind | Signature |
|---|---|---|
siteUrl |
filter | ($url = '', $prefix = null, $current_prefix = true) |
siteUrl |
function | ($url = '', $prefix = null, $current_prefix = true) |
startTimer |
function | () |
stopTimer |
function | ($name) |
markTime |
function | ($name) |
debugOutput |
function | () |
siteUrl forwards to Router::siteUrl(); the three timer functions forward to Timers;
debugOutput returns Logger::debugOutput(). \StaticPHP\Utils\Models\Csrf::registerTwig()
is then called, which adds the csrfToken(), csrfFieldName() and csrfField() helpers -
registering them only makes the token reachable from a template, validating an incoming
request is still the application’s job.
If twig is not installed, none of this exists and Load::view() renders plain php
templates instead. See Load.
The application autoloader
Section titled “The application autoloader”Step 2 above also registers a second spl_autoload_register() callback, in
src/Core/Helpers/Autoload.php. It is what resolves the application tree, whose namespace
roots are module names rather than a PSR-4 prefix - see
the front controller for what it
resolves and how, and
running multiple applications for why it
exists at all.