getenv

Reads the value of one environment variable, or returns all of them as an array.

Signature
getenv(?string $name = null, bool $local_only = false): string|array|false
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$nameoptional?string= nullThe name of the environment variable to read. Pass null or omit it to get every variable as an associative array.
$local_onlyoptionalbool= falseWhen true, only variables set by the operating system or by putenv() are returned, ignoring values injected by the SAPI. Only has an effect when name is a string.

Return value

string|array|falseThe value of the named environment variable as a string, or false if it is not set. When name is null or omitted, an associative array of all environment variables is returned.

Changelog

  • PHP 8.0.0The name parameter is now nullable.
  • PHP 7.1.0name can be omitted to retrieve an associative array of all environment variables.
  • PHP 7.0.9The local_only parameter was added.

getenv() is how a PHP process reads configuration handed to it by the shell, the container runtime, systemd or the web server. It is the usual home for values you must not commit: database passwords, API keys, and per-environment hostnames.

Reading and defaulting

A missing variable returns false, and an empty variable returns "". Both are falsy, so getenv('X') ?: 'default' quietly substitutes the default for a deliberately blank value. When the distinction matters, compare against false explicitly. Note also that ?? does not help here — the function returns false, never null, so the null-coalescing operator never fires.

The SAPI trap

Under a web SAPI, getenv() also sees variables the server passed in with the request, which for some setups includes client-controlled headers. Passing true as the second argument restricts the lookup to real process variables set by the OS or by putenv(). The common safe pattern is to try local first and fall back: getenv('REMOTE_ADDR', true) ?: getenv('REMOTE_ADDR').

Everything getenv() returns is a string. "false", "0" and "off" are all non-empty strings, so cast or validate booleans and integers yourself.

Example

Example · php
<?php

// getenv() is disabled in this sandbox; this is how it is normally used.
$dsn = getenv('DATABASE_URL');

if ($dsn === false) {
    exit("DATABASE_URL is not set\n");
}

$debug = filter_var(getenv('APP_DEBUG') ?: 'false', FILTER_VALIDATE_BOOL);
$port  = (int) (getenv('APP_PORT') ?: 8080);

echo "dsn:   {$dsn}\n";
echo "debug: ", var_export($debug, true), "\n";
echo "port:  {$port}\n";

When to use it

  • Read a database password or API key that a container runtime injected instead of storing it in a file.
  • Switch between staging and production endpoints based on an APP_ENV variable.
  • Detect a CI run so a test suite can skip steps that need a real network.

Frequently asked questions

What is the difference between getenv and $_ENV?

$_ENV is a snapshot array built at startup and is often empty because the variables_order ini setting frequently omits E. getenv() queries the live process environment every time, so it also sees anything putenv() has set since, which makes it the more reliable option.

Why does getenv return false instead of null?

It has returned false for a missing variable since PHP 4 and that has never changed. The practical consequence is that ?? does nothing useful with it — use ?: for a default, or compare with === false when an empty value must be distinguished from a missing one.

What does the local_only parameter in getenv do?

It restricts the lookup to variables set by the operating system or by putenv(), ignoring anything the web server SAPI added for the request. That matters because some SAPI-provided values derive from client-controlled headers, so local_only gives you a value that a request cannot forge.

More examples

Safe read with a typed default

This is the wrapper most projects end up writing: it prefers the local process variable over anything the SAPI injected, converts the usual boolean spellings, and turns numeric strings into real numbers so a port is an int rather than "8080". Cannot run here because getenv() is disabled in the sandbox.

Example · php
<?php

function env(string $key, string|int|bool|null $default = null): string|int|bool|null
{
    $raw = getenv($key, true) ?: getenv($key);
    if ($raw === false) {
        return $default;
    }
    return match (strtolower($raw)) {
        'true', 'on', 'yes' => true,
        'false', 'off', 'no' => false,
        '' => $default,
        default => is_numeric($raw) ? $raw + 0 : $raw,
    };
}

var_dump(env('APP_DEBUG', false), env('APP_PORT', 8080));

List every environment variable

Calling getenv() with no arguments returns the whole environment as an associative array, which is useful for a diagnostics page — with anything that looks like a credential masked before it is printed. Cannot run here because getenv() is disabled in the sandbox.

Example · php
<?php

$all = getenv();          // PHP 7.1+ : omit the name to get them all
ksort($all);

foreach ($all as $name => $value) {
    if (preg_match('/(KEY|SECRET|TOKEN|PASSWORD)/i', $name)) {
        $value = str_repeat('*', 8);   // never print credentials
    }
    printf("%-24s %s\n", $name, $value);
}

echo count($all), " variables\n";

Distinguishing unset from empty

An empty variable and a missing variable both look falsy, so the last line prints "default" even though the operator deliberately set the flag to empty. Comparing against false is the only way to tell them apart. Cannot run here because getenv() and putenv() are disabled in the sandbox.

Example · php
<?php

putenv('FEATURE_FLAG=');   // set, but empty

var_dump(getenv('FEATURE_FLAG'));            // string(0) ""
var_dump(getenv('FEATURE_FLAG') === false);  // bool(false) - it IS set
var_dump(getenv('NOT_SET_AT_ALL'));          // bool(false)

// The common bug: ?: cannot tell the two apart
var_dump(getenv('FEATURE_FLAG') ?: 'default');

Discussion

  • Be the first to comment on this lesson.