In PHP, how do getenv() and putenv() work, and what does getenv() return for a variable that is not set?
answer
- string, array or false
- no argument returns every variable
- putenv("NAME=value") takes one string
- the ?: fallback swallows "0"
- putenv changes vanish at request end
basics
~20 sgetenv('NAME') returns the variable's value as a string, or false when it is not set; getenv() with no argument returns all of them as an array. putenv('NAME=value') sets a variable for the current process and its children until the request ends.
solid answer
~40 s`getenv(?string $name = null, bool $local_only = false): string|array|false` reads the environment. With a name it returns the value as a `string` or `false` if the variable does not exist; with no name it returns an array of all variables. Because a missing variable is `false` and an empty one is `''`, compare with `=== false` when the difference matters, and remember that `getenv('X') ?: 'default'` also replaces `'0'`. `putenv('NAME=value')` takes one `NAME=value` string, returns `bool`, and changes the environment of the current process, which child processes started later inherit. It does not update `$_ENV` or `$_SERVER`, and PHP restores the previous value when the request ends. `putenv('NAME')` without `=` unsets the variable.
code
php · 17 lines<?php
declare(strict_types=1);
$host = getenv('DB_HOST');
if ($host === false) {
throw new RuntimeException('DB_HOST is not set');
}
$port = getenv('DB_PORT');
$port = $port === false ? 5432 : (int) $port; // '0' is kept, only absence defaults
putenv('APP_ENV=staging'); // set
var_dump(getenv('APP_ENV')); // string(7) "staging"
var_dump($_ENV['APP_ENV'] ?? null); // NULL: putenv() does not touch $_ENV
putenv('APP_ENV'); // unset
var_dump(getenv('APP_ENV')); // bool(false)go deeper
Recall that getenv('NAME') returns a string or false, that values are always strings, and that putenv() takes a single 'NAME=value' string.
Explain why ?: is the wrong fallback for '0', why $_ENV does not see putenv() changes, and what local_only changes under FPM.
Show that you read environment once at boot into typed config, fail fast on missing required values, and scope child-process variables explicitly rather than with putenv().
Treat the environment as process-wide shared state and set a team rule on where configuration is read and validated, so no library calls getenv() on its own.
## What the environment is Every process on Unix-like systems and Windows carries a list of **environment variables**: name/value string pairs inherited from whatever started it — a shell, a container runtime, a process manager. Deployments use them to pass settings such as `APP_ENV=production` or `DB_HOST=db.internal` to a program without changing its code. ## Reading with `getenv()` The signature in `ext/standard/basic_functions.stub.php` is: `getenv(?string $name = null, bool $local_only = false): string|array|false` | Call | Returns | |---|---| | `getenv('DB_HOST')` when set | the value as a `string` (possibly `''`) | | `getenv('DB_HOST')` when not set | `false` | | `getenv()` | an `array` of every variable, name => value | Values are always strings. A variable holding `5432` comes back as `'5432'`; casting is your job. The `$local_only` flag matters under web SAPIs. Without it, `getenv()` first asks the SAPI — under PHP-FPM that means the FastCGI parameters the web server sent with the request — and only then the process environment. With `local_only: true` it reads the process environment alone. ## The `false` versus empty-string trap Two common fallback styles behave differently: - `getenv('DB_PORT') ?: '5432'` — `?:` treats `false`, `''` and `'0'` all as "missing", so a variable deliberately set to `0` is silently replaced. - `getenv('DB_PORT') === false ? '5432' : getenv('DB_PORT')` — only a truly absent variable gets the default. For required settings, fail fast instead of defaulting: if `getenv('DB_PASSWORD') === false`, throw during boot with a clear message, rather than connecting with an empty password. ## Writing with `putenv()` `putenv(string $assignment): bool` takes **one** string in `NAME=value` form: 1. `putenv('APP_ENV=staging')` sets or replaces the variable. 2. `putenv('APP_ENV')` — no equals sign — removes it. 3. `putenv('')` or `putenv('=x')` throws a `ValueError` ("must have a valid syntax"). The change goes into the real process environment, so: - later `getenv('APP_ENV')` calls in the same process see it; - child processes started afterwards (for example with `proc_open()` or `exec()`) inherit it; - `$_ENV` and `$_SERVER` are **not** updated — they were filled when the request started. ## Changes are undone at request end PHP records each variable it changes together with the previous value. When the request shuts down, it puts the old values back and removes variables that did not exist before. Under PHP-FPM this stops one request's `putenv()` leaking into the next request served by the same worker. In a CLI script the "request" is the whole run, so the change lasts until the script ends. ## When to use which - **Reading configuration:** `getenv()` (or `$_ENV`/`$_SERVER` when your setup fills them), once at boot, into a typed config object. - **Passing a value to a child process:** prefer giving `proc_open()` an explicit environment array over `putenv()`, because it is scoped to that one child. - **Tests:** `putenv()` is a convenient way to set a variable for code that calls `getenv()`, but restore it afterwards, since the whole process shares it. The environment is also process-wide state shared by every thread of the process, so on thread-safe (ZTS) builds `putenv()` is a poor fit for per-request data.
- Why is getenv('DEBUG') ?: 'on' a bug when DEBUG=0 is set?`?:` returns its right side whenever the left side is falsy, and in PHP the string `'0'` is falsy, as are `''` and `false`. So an explicit `DEBUG=0` is replaced by `'on'`. Test `getenv('DEBUG') === false` to default only when the variable is absent.
- Does a putenv() call in one PHP-FPM request affect the next request on the same worker?No. PHP stores the previous value of every variable `putenv()` changes and restores it, or removes the variable, when the request shuts down. The next request starts with the worker's original environment. Within the request, though, child processes started after the call do inherit the change.
saying these in an interview costs you the question
- getenv() returns null for a variable that is not set
- putenv() also adds the value to $_ENV and $_SERVER
- putenv() takes the name and the value as two arguments
- getenv('X') ?: 'default' only applies the default when X is missing
- getenv() converts numeric values to int