$_ENV

Ma Mariya Vinciya Updated 21 Oct 2026
6 min read ·Lesson 155 of 174
In this post

What Are Environment Variables? In simple terms: Environment variables are named settings provided by the system that runs your program — for example, the database password, the API key for a payment

What Are Environment Variables?

In simple terms: Environment variables are named settings provided by the system that runs your program — for example, the database password, the API key for a payment service, or whether the application runs in "development" or "production" mode. The code stays the same everywhere; only the environment changes.

Technically: Every process on Linux, macOS, and Windows has an environment: a set of NAME=value strings inherited from the process that started it (a shell, a web server, a container runtime, or a process manager). PHP exposes them through the $_ENV superglobal (when enabled), through getenv(), and — depending on the server API — through $_SERVER.

Why Configuration Belongs in the Environment

Hard-coding settings causes real problems:

// Bad: credentials inside the code

\$pdo \= new PDO('mysql:host=localhost;dbname=shop', 'root', 'MySecretPass123');

 

  • Secrets leak when the code is pushed to a Git repository or shared.
  • Different environments (your laptop, a staging server, production) need different values, so the code would have to be edited for each.

Reading configuration from the environment solves both problems: the same code reads DB_PASSWORD, and each machine provides its own value. This approach is a core principle of the widely used Twelve-Factor App methodology.


$_ENV Is Often Empty

<?php

// Run: php env-check.php

var_dump(count(\$_ENV));

var_dump(getenv('HOME'));

var_dump(getenv('DOES_NOT_EXIST'));

 

int(0)

string(10) "/home/asha"

bool(false)

 

Why $_ENV Is Empty

$_ENV is filled only if the variables_order setting contains the letter E. The recommended php.ini files set variables_order = "GPCS" — without E — for performance reasons, so $_ENV stays empty. The environment variables still exist; they are simply not copied into $_ENV.

MethodWorks With Recommended Settings?Notes
getenv('NAME')YesReturns the value as a string, or false if not set
$_SERVER['NAME']UsuallyDepends on the server API; the CLI includes environment variables
$_ENV['NAME']Only if variables_order contains E, or a library fills itMany .env loaders write values here

 


Setting Environment Variables

Command Line

APP_ENV=production DB_PORT=3307 php config.php

 

Variables placed before the command apply to that process only.

Web Servers and PHP-FPM

EnvironmentHow to Set Variables
ApacheSetEnv APP_ENV production in the virtual host configuration
Nginx + PHP-FPMfastcgi_param APP_ENV production; in Nginx, or env[APP_ENV] = production in the FPM pool configuration
Dockerenvironment: in docker-compose.yml, or -e APP_ENV=production
Hosting panels and PaaSA "Environment Variables" settings page

 

PHP-FPM note: By default, FPM's clear_env = yes setting removes environment variables inherited from the shell that started FPM. Define variables explicitly with env[...] in the pool configuration (or set clear_env = no).


.env Files for Local Development

During development, it is convenient to keep settings in a .env file in the project root:

APP_ENV=local
APP_DEBUG=true
DB_HOST=127.0.0.1
DB_PORT=3306
DB_NAME=shop
DB_USER=shop_user
DB_PASSWORD=change-me

 

PHP does not read .env files by itself. The popular library vlucas/phpdotenv loads them (and frameworks such as Laravel use it):

composer require vlucas/phpdotenv

 

<?php

require __DIR__ . '/vendor/autoload.php';

 

\$dotenv \= Dotenv\Dotenv::createImmutable(__DIR__);

\$dotenv->safeLoad();

\$dotenv->required(['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASSWORD']);

 

echo \$_ENV['DB_NAME'];

 

How It Works

  • createImmutable() reads .env but does not overwrite variables that already exist in the real environment. This lets a server's real environment variables take priority over the file.
  • safeLoad() does not fail if the .env file is missing (typical in production, where real environment variables are used); load() would throw an exception.
  • required() throws an exception at startup if essential settings are missing, so misconfiguration is discovered immediately rather than at the first database query.
  • Loaded values are placed in $_ENV and $_SERVER.

Keep .env Out of Version Control

# .gitignore
.env

 

Commit a .env.example file with the variable names and harmless placeholder values instead, so other developers know what to configure. Also make sure the .env file is outside the public web root, so it can never be downloaded through a URL.


Reading Configuration With Defaults and Types

Environment values are always strings. A small helper can provide defaults and convert common literal values:

<?php

// config.php

function env(string \$key, mixed \$default \= null): mixed

{

    \$value \= \$_ENV[\$key] ?? \$_SERVER[\$key] ?? getenv(\$key);

 

    if (\$value \=== false || \$value \=== null) {

        return \$default;

    }

 

    return match (strtolower(trim(\$value))) {

        'true' \=> true,

        'false' \=> false,

        'null' \=> null,

        '' \=> \$default,

        default \=> \$value,

    };

}

 

\$config \= [

    'env' \=> env('APP_ENV', 'local'),

    'debug' \=> env('APP_DEBUG', true),

    'db_host' \=> env('DB_HOST', '127.0.0.1'),

    'db_port' \=> (int) env('DB_PORT', 3306),

];

 

var_export(\$config);

echo "\n";

 

Run

APP_ENV=production APP_DEBUG=false DB_PORT=3307 php config.php

 

Output

array (

  'env' \=> 'production',

  'debug' \=> false,

  'db_host' \=> '127.0.0.1',

  'db_port' \=> 3307,

)

 

Step-by-Step Explanation

  1. The helper checks $_ENV, then $_SERVER, then getenv(), so it works whether values come from a .env loader or the real environment.
  2. The string 'false' is converted to the boolean false. Without this, if (getenv('APP_DEBUG')) would treat 'false' as true, because any non-empty string is truthy.
  3. DB_HOST is not set, so the default is used.
  4. Numeric settings are cast explicitly with (int).

Laravel's env() helper follows the same idea. In frameworks, env() is typically called only inside configuration files, and the rest of the application reads the resulting configuration values.


Security Considerations

  • Never print the environment. phpinfo(), debug pages, and error reports can display all environment variables, including passwords. Disable debug output in production and never leave phpinfo() pages online.
  • Do not log secrets. Mask passwords and tokens when logging configuration.
  • Limit access. Restrict who can read server configuration files and .env files.
  • Prefer $_ENV/$_SERVER in threaded environments. getenv() and putenv() are not thread-safe in multi-threaded server setups; libraries like phpdotenv therefore write to $_ENV and $_SERVER by default.
  • Consider dedicated secret managers (cloud secret stores, Vault) for large or regulated systems.

Common Mistakes

Expecting $_ENV to Contain Values

Effect: $_ENV['DB_HOST'] is undefined with the recommended php.ini.

Fix: Use getenv(), a .env loader, or a helper that checks several sources.

Treating 'false' as Boolean

Effect: Debug mode turns on when APP_DEBUG=false.

Fix: Convert strings explicitly ('true'/'false').

Committing .env Files

Effect: Credentials are exposed in the repository history.

Fix: Ignore .env in Git, commit .env.example, and rotate any leaked secrets.

Forgetting PHP-FPM's clear_env

Effect: Variables set in the shell are missing in web requests.

Fix: Configure env[...] entries in the FPM pool.

Reading Environment Variables Throughout the Code

Effect: Hidden dependencies scattered across the application.

Fix: Read the environment once into a configuration array or object, and pass configuration where it is needed.


Best Practices

  • Store credentials and environment-specific settings in environment variables, never in code.
  • Use .env files only for local development, keep them out of Git, and validate required variables at startup.
  • Convert values to the correct types and provide defaults in one central configuration step.
  • Never expose environment variables through phpinfo(), error pages, or logs.

Official reference: https\://www.php.net/manual/en/reserved.variables.environment.php

 

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else User-defined Functions Slicing Strings PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention Garbage Collection Project: Simple Blog PHP What is OOP PHP Classes/Objects The $this Keyword Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where Debugging PHP Project: Image Upload Gallery $_SESSION $_ENV PHP RegEx RegEx Patterns Heredoc and Nowdoc RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures Composer
Ask about this post
AI Ask about this post

Ask questions about $_ENV and get answers drawn from it.

Signed-in readers only.