111

What is the difference between getenv() and $_ENV?

Any trade-offs between using either?

I noticed sometimes getenv() gives me what I need, while $_ENV does not (such as HOME).

Palec
  • 12,743
  • 8
  • 69
  • 138
tau
  • 6,499
  • 10
  • 37
  • 60
  • 1
    Don’t get trapped by PHP hiding the gory details from you. `$_ENV` and `$_SERVER` are populated with data obtained in various ways. `getenv()` is yet another way to access data that PHP does not enable you to access directly. It works even with `variables_order = "G"`, when `$_SERVER` and `$_ENV` are empty. Read the great answer by [Conor McDermottroe](http://stackoverflow.com/a/21473853/2157640). – Palec Aug 09 '15 at 18:42
  • Related: [Why is my $_ENV empty?](http://stackoverflow.com/q/3780866/2157640) – Palec Aug 09 '15 at 18:43
  • 5
    For those, who are using Symfony framework, there is one more limited case of the above. getenv() will always return the value of env variable as it was when php server started, even if afterwards it was changed. While $_ENV[] can be changed in runtime by modifiing .env files. But of course it relates to Symfony, and not PHP in general. – Ross Nov 27 '19 at 06:44

9 Answers9

74

According to the php documentation about getenv, they are exactly the same, except that getenv will look for the variable in a case-insensitive manner when running on case-insensitive file systems (like Windows). On Linux hosts it still works as case-sensitive. Most of the time it probably doesn't matter, but one of the comments on the documentation explains:

For example on Windows $_SERVER['Path'] is like you see, with the first letter capitalized, not 'PATH' as you might expect.

Because of that, I would probably opt to use getenv to improve cross-platform behavior, unless you are certain about the casing of the environment variable you are trying to retrieve.

Steve Clay's comment in this answer highlights another difference:

Added getenv() advantage: you don't need to check isset/empty before access. getenv() won't emit notices.

Dinei
  • 4,494
  • 4
  • 36
  • 60
Batkins
  • 5,547
  • 1
  • 28
  • 27
58

I know that the comment in the docs says that getenv is case-insensitive, but that's not the behaviour I'm seeing:

> env FOO=bar php -r 'print getenv("FOO") . "\n";'
bar
> env FOO=bar php -r 'print getenv("foo") . "\n";'

> env foo=bar php -r 'print getenv("foo") . "\n";'
bar
> env foo=bar php -r 'print getenv("FOO") . "\n";'

> php --version
PHP 5.4.24 (cli) (built: Jan 24 2014 03:51:25)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies

Looking at the source code for the getenv function, this is because there are three ways that PHP can fetch the environment variable:

  1. Via sapi_getenv (e.g. if it's getting the environment variable from Apache)
  2. If on Windows, from GetEnvironmentVariableA.
  3. If on non-Windows, from the getenv function provided by libc.

As far as I can tell, the only time when it will behave in a case-insensitive manner is on Windows because that's how the Windows environment variable API behaves. If you're on Linux, BSD, Mac, etc then getenv is still case sensitive.

As mentioned by mario, $_ENV is not always populated due to different configurations of variables_order so it's best if you avoid $_ENV if you don't control the server configuration.

So, for the most portable PHP code:

  1. Use getenv.
  2. Use the correct case for the environment variable name.
Conor McDermottroe
  • 1,333
  • 9
  • 10
49

Additionally $_ENV is typically empty if variables_order does't have E listed. On many setups it's likely that only $_SERVER is populated, and $_ENV is strictly for CLI usage.

On the other hand getenv() accesses the environment directly.

(Regarding the case-ambiguity, one could more simply employ array_change_key_case().)

mario
  • 144,265
  • 20
  • 237
  • 291
6

I found getenv() useful to avoid a strange PHP bug where sometimes $_SERVER and $_ENV was undefined if auto_globals_jit was enabled (creating the _SERVER and _ENV variables when they're first used). Since then I began to to use it.

Leopoldo Sanczyk
  • 1,529
  • 1
  • 26
  • 28
3

I'd add that getenv() is a better choice because, as a function, it can be overloaded for testing purposes. Whereas overwriting your $_SERVER or $_ENV variables might interfere with test frameworks and other libraries and ultimately require a lot more work to carry out safely.

Joe Green
  • 1,745
  • 1
  • 12
  • 17
3

I think the existing answers give a good overview of any differences in usage, but it might also be worth bearing in mind that the maintainers of the popular PHP library for loading environment variables recommend to avoid using getenv

https://github.com/vlucas/phpdotenv

Using getenv() and putenv() is strongly discouraged due to the fact that these functions are not thread safe

mickadoo
  • 3,337
  • 1
  • 25
  • 38
3

Taken from the PHP docs:

This function is useful (compared to $_SERVER, $_ENV) because it searches $varname key in those array case-insensitive manner. For example on Windows $_SERVER['Path'] is like you see Capitalized, not 'PATH' as you expected. So just: <?php getenv('path') ?>

Ayman Safadi
  • 11,502
  • 1
  • 27
  • 41
1

$_ENV is a superglobal array that contains all the environment variables. You can access a specific environment variable by using its name as the key in the $_ENV array. For example, $_ENV['DB_HOST'] would give you the value of the DB_HOST environment variable.

getenv() is a function that takes the name of an environment variable as its argument and returns its value. For example, getenv('DB_HOST') would give you the value of the DB_HOST environment variable.

The main difference between the two is that $_ENV is a superglobal array, which means that it is always available in your PHP code, while getenv() is a function that you need to call explicitly.

-5

read env and create

<?php

namespace neoistone;

class ns_env {
    
    
    /**
     * env to array file storage
     *
     * @param $envPath
     */
    public static function envToArray(string $envPath)
    {
        $variables = [];
        $mread = fopen($envPath, "r");
        $content = fread($mread,filesize($envPath));
        fclose($mread);
        $lines = explode("\n", $content);
        if($lines) {
            foreach($lines as $line) {
                // If not an empty line then parse line
                if($line !== "") {
                    // Find position of first equals symbol
                    $equalsLocation = strpos($line, '=');

                    // Pull everything to the left of the first equals
                    $key = substr($line, 0, $equalsLocation);

                    // Pull everything to the right from the equals to end of the line
                    $value = substr($line, ($equalsLocation + 1), strlen($line));

                    $variables[$key] = $value;

                } else {
                    $variables[] = "";
                }
            }
        }
        return $variables;
    }
  
    /**
     * Array to .env file storage
     *
     * @param $array
     * @param $envPath
     */
    public static function arrayToEnv(array $array, string $envPath)
    {
        $env = "";
        $position = 0;
        foreach($array as $key => $value) {
            $position++;
            // If value isn't blank, or key isn't numeric meaning not a blank line, then add entry
            if($value !== "" || !is_numeric($key)) {
                // If passed in option is a boolean (true or false) this will normally
                // save as 1 or 0. But we want to keep the value as words.
                if(is_bool($value)) {
                    if($value === true) {
                        $value = "true";
                    } else {
                        $value = "false";
                    }
                }

                // Always convert $key to uppercase
                $env .= strtoupper($key) . "=" . $value;

                // If isn't last item in array add new line to end
                if($position != count($array)) {
                   $env .= "\n";
                }
            } else {
                $env .= "\n";
            }
        }
        $mwrite = fopen($envPath, "w");
        fwrite($mwrite, $env);
        fclose($mwrite);
    }
    /**
     * Json to .env file storage
     *
     * @param $json
     * @param $envPath
     */
    public static function JsonToEnv(array $json, string $envPath)
    {
        $env = "";
        $position = 0;
        $array = json_decode($json,true);
        foreach($array as $key => $value) {
            $position++;
            // If value isn't blank, or key isn't numeric meaning not a blank line, then add entry
            if($value !== "" || !is_numeric($key)) {
                // If passed in option is a boolean (true or false) this will normally
                // save as 1 or 0. But we want to keep the value as words.
                if(is_bool($value)) {
                    if($value === true) {
                        $value = "true";
                    } else {
                        $value = "false";
                    }
                }

                // Always convert $key to uppercase
                $env .= strtoupper($key) . "=" . $value;

                // If isn't last item in array add new line to end
                if($position != count($array)) {
                   $env .= "\n";
                }
            } else {
                $env .= "\n";
            }
        }
        $mwrite = fopen($envPath, "w");
        fwrite($mwrite, $env);
        fclose($mwrite);
    }
    /**
     * XML to .env file storage
     *
     * @param $json
     * @param $envPath
     */
    public static function XmlToEnv(array $xml, string $envPath)
    {
        $env = "";
        $position = 0;
        $array = simplexml_load_string($xml);
        foreach($array as $key => $value) {
            $position++;
            // If value isn't blank, or key isn't numeric meaning not a blank line, then add entry
            if($value !== "" || !is_numeric($key)) {
                // If passed in option is a boolean (true or false) this will normally
                // save as 1 or 0. But we want to keep the value as words.
                if(is_bool($value)) {
                    if($value === true) {
                        $value = "true";
                    } else {
                        $value = "false";
                    }
                }

                // Always convert $key to uppercase
                $env .= strtoupper($key) . "=" . $value;

                // If isn't last item in array add new line to end
                if($position != count($array)) {
                   $env .= "\n";
                }
            } else {
                $env .= "\n";
            }
        }
        $mwrite = fopen($envPath, "w");
        fwrite($mwrite, $env);
        fclose($mwrite);
    }
}
?>