Environment Architecture
The package has two separate runtime models: one for .env loading and one for server metadata access.
Environment loading flow
A typical environment read follows this path:
env()
-> environment()
-> Di-managed Environment instance
-> Environment::getValue($key, $default)
Before reads work, the shared Environment instance must be initialized:
Environment::load(Setup $setup)
-> ensure Loader is registered in DI
-> Di::get(Loader::class)->setup($setup)->load()
-> read app_env from loaded config
-> choose .env or .env.<app_env>
-> Dotenv::createArrayBacked(...)->load()
-> cache loaded values in $envContent
Environment lifecycle
Environment keeps three pieces of state that matter:
$loadedprevents reloading after the first successful load$envContentstores the loaded key/value map$appEnvstores the selected environment name
Practical effect:
- one process can load at most one environment file per shared
Environmentinstance - changing the setup or changing the file on disk has no effect after load unless the instance is replaced
getAppEnv()and theisProduction()/isStaging()/isDevelopment()/isTesting()/isLocal()helpers all read that cached$appEnvvalue
File selection model
Environment::load() defaults to production when app_env is missing from the loaded config.
Selection logic is literal:
production->.env- anything else ->
.env.<value>
There is no validation that app_env matches one of the Env constants.
Mutation model
updateRow() modifies both the file on disk and the in-memory $envContent cache.
When the key already exists, the method:
- reads the whole environment file
- replaces the exact
KEY=currentValueline withKEY=newValue - writes the full file back
When the key does not exist, it appends a new KEY=value line.
Because the replacement pattern is built from the current cached value, the method is designed for values that still match the file content exactly.
Server lifecycle
server() resolves Server through DI. The object copies $_SERVER once in __construct() and then serves all reads from its private $server property.
That makes Server a mutable snapshot object:
set()mutates only the internal copyflush()empties only the internal copyall(),get(), and the convenience accessors read only the internal copy
Header normalization flow
Server::getAllHeaders() scans the stored server array and includes only keys that begin with HTTP_.
For each header key it:
- removes the
HTTP_prefix - converts underscores to hyphens
- lowercases the result
So HTTP_X_REQUEST_ID becomes x-request-id.
Keys such as CONTENT_TYPE are not included by this method because they do not start with HTTP_.