95

I'm running Apache/2.2.11 (Win32) PHP/5.3.0 and I did the following in my .htaccess file:

SetEnv FOO bar

If I print out the $_ENV variable in a PHP file, I get an empty array. Why doesn't my environment variable appear there? Why is it empty in the first place?

I did find my variable though, but it appears in the $_SERVER variable. And for some reason it appears twice, sort of. Why is this?

[REDIRECT_FOO] => bar
[FOO] => bar

It appears I can get it using getenv('FOO'), so maybe I should just use that instead. But I am still a bit curious to what causes this. Is this a Windows issue? Or what is going on?

Svish
  • 152,914
  • 173
  • 462
  • 620
  • 2
    Not a Windows issue, it's the same in Linux (running PHP as a module). I'm not sure about the details, but it may be the enivronment of the webserver is not the same as that of PHP, and that's why it gets sent as a `$_SERVER` var. I'd give my vote for using `getenv()` which just searches them both case-insensitive as far as I gather. – Wrikken Sep 23 '10 at 17:21
  • 1
    On a side note: the CLI instance _does_ get it in `$_ENV`. – Wrikken Sep 23 '10 at 17:23
  • @svish Your update helped me. If you changed it to an answer I'd happily upvote it. – Dominic Sayers Mar 31 '13 at 20:38
  • @svish Your solution posted in the question should really be posted as an answer below. This question has been linked several times as a duplicate close target, but the solution is out of place up in the question :) – Michael Berkowski Nov 22 '14 at 03:49
  • @MichaelBerkowski Thanks for the note. Good idea. Doing it now :) – Svish Nov 22 '14 at 12:27

3 Answers3

148

Turns out there was two issues here:

1. $_ENV is only populated if php.ini allows it, which it doesn't seem to do by default, at least not in the default WAMP server installation.

; This directive determines which super global arrays are registered when PHP
; starts up. If the register_globals directive is enabled, it also determines
; what order variables are populated into the global space. G,P,C,E & S are
; abbreviations for the following respective super globals: GET, POST, COOKIE,
; ENV and SERVER. There is a performance penalty paid for the registration of
; these arrays and because ENV is not as commonly used as the others, ENV is
; is not recommended on productions servers. You can still get access to
; the environment variables through getenv() should you need to.
; Default Value: "EGPCS"
; Development Value: "GPCS"
; Production Value: "GPCS";
; http://php.net/variables-order
variables_order = "GPCS"

When I set the variables_order back to EGPCS, $_ENV is no longer empty.

2. When you use SetEnv in your .htaccess, it ends up in $_SERVER, not in $_ENV, which I gotta say is a tad confusing when it's named SetEnv...

# .htaccess
SetEnv ENV dev
SetEnv BASE /ssl/

# php
var_dump($_SERVER['ENV'], $_SERVER['BASE']);

// string 'dev' (length=3)
// string '/ssl/' (length=5)

3. The getenv function will always work and is not affected by the PHP setting for $_ENV Additionally it seems to do so insensitive to case, which might be useful.

var_dump(getenv('os'), getenv('env'));

// string 'Windows_NT' (length=10)
// string 'dev' (length=3)
Erik Kalkoken
  • 30,467
  • 8
  • 79
  • 114
Svish
  • 152,914
  • 173
  • 462
  • 620
  • 8
    AGGH! Thank you so much!!! You have no idea how long I've been googling around thinking there was a problem with mod_env or something. I completely forgot about variables_order! Thank you for being awesome!!! – Marcel Oct 24 '15 at 01:12
  • 1
    Seems like the value should be set without quotes now. (Error `PHP: syntax error, unexpected '"' in php.ini`) – yanot Jul 26 '18 at 08:10
  • 1
    Thank you! Say, can you separate this out into three answers so I can upvote it three times? :D – Doug McLean Oct 16 '20 at 09:11
  • Always use `$_SERVER`. `getenv()` is not thread-safe: https://stackoverflow.com/questions/30476600/how-can-getenv-be-thread-safe – jlh Jan 14 '22 at 08:55
  • @jlh Why does that matter? Nothing `getenv` returns should be changing anyways. – Svish Jan 14 '22 at 12:52
  • @Svish Calling `getenv()` multiple times may return different values, depending on how other threads are using `putenv()`. So yes, it matters. – jlh Jan 14 '22 at 12:55
  • Not if you're not using `putenv`, which I've never used ever. – Svish Jan 14 '22 at 22:27
13

$_ENV variables are imported from the environment under which PHP is running, and depending on your setup (the OS, your server, whether PHP runs as an Apache module or under FastCGI, etc.), this can vary greatly.

IIRC in a standard Apache+mod_php install on Windows, the only way to change variables in $_ENV is to change Windows' environment variables (see this). This can be significant when dealing with PHP extensions on Windows, because some of them (eg: php_ldap) are only configurable through environment vars on $_ENV.

NullUserException
  • 83,810
  • 28
  • 209
  • 234
2

REDIRECT_* variables appear if you are using RewriteRules. On my server they also appear just so. It might have something to do with running under FastCGI. And if combined with suexec, that's most likely to clean up the complete environment var pool. There might be additional configuration necessary to get them back, PassEnv particularily. As to why getenv() works for you, I have no clue. But all phenomena are specific to your server and php configuration. Ask on serverfault, they should know.

mario
  • 144,265
  • 20
  • 237
  • 291
  • Aha. I guessed the rewrite module might have something to do with it. Just can't quite imagine out why it's done. But I'm sure Apache has its reasons :p (or bugs) – Svish Sep 23 '10 at 20:24
  • 2
    In case you've lost sleep over why `getenv` worked: Just found out it apparently searches `$_ENV` *and* `$_SERVER` :p – Svish Nov 22 '14 at 12:47