> For the complete documentation index, see [llms.txt](https://quantumphp.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://quantumphp.gitbook.io/docs/packages/environment/architecture.md).

# 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:

* `$loaded` prevents reloading after the first successful load
* `$envContent` stores the loaded key/value map
* `$appEnv` stores the selected environment name

Practical effect:

* one process can load at most one environment file per shared `Environment` instance
* changing the setup or changing the file on disk has no effect after load unless the instance is replaced
* `getAppEnv()` and the `isProduction()` / `isStaging()` / `isDevelopment()` / `isTesting()` / `isLocal()` helpers all read that cached `$appEnv` value

## 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:

1. reads the whole environment file
2. replaces the exact `KEY=currentValue` line with `KEY=newValue`
3. 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 copy
* `flush()` empties only the internal copy
* `all()`, `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:

1. removes the `HTTP_` prefix
2. converts underscores to hyphens
3. 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_`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://quantumphp.gitbook.io/docs/packages/environment/architecture.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
