PHP-DI icon indicating copy to clipboard operation
PHP-DI copied to clipboard

Cannot set an env var to false, as it gets interpreted as missing

Open Crell opened this issue 1 year ago • 4 comments

I have an env var set via a .env file, which is populated into the environment by Symfony/dotenv. It is defined like so:

ENABLE_CACHE=false

This creates a problem, because EnvironmentVariableResolver::getEnvVariable() will then dutifully return false as the value of the variable. However, the resolve() method of the same class then does this:

if (false !== $value) {
    return $value;
}

Presumably because getenv() wrongly uses false as its not-found value. But the net result is that it's impossible to set an env var to false, because it gets confused with "missing" (ie, not found in $_ENV, $_SERVER, or getenv(), so getenv()'s false return value is used). This is not good.

The correct solution, IMO, is to use a sentinel single-value-enum to indicate not-found, instead of an otherwise legitimate value. Baring that, returning null from getEnvVariable() to indicate not-found would likely also work, or at least conflict with fewer legitimate uses.

Crell avatar Feb 07 '25 05:02 Crell

Addendum: I just verified, and I have additional code that is folding $_ENV['ENABLE_CACHE'] to a boolean rather than a string, early in the process, after DotEnv has loaded it. That's likely why I'm the first to run into this issue. However, that seems necessary to me given that on/off toggles are a very common use of env vars, and those really should be booleans in the code base for hopefully self-evident reasons. This issue should still be corrected.

Crell avatar Feb 07 '25 06:02 Crell

Environment variables cannot be booleans in the strict sense of the term, as you said the root issue might be here:

I have additional code that is folding $_ENV['ENABLE_CACHE'] to a boolean rather than a string

I'm not sure we should account for code that changes the behavior of an environment variable to something non-standard. AFAIK the usual practice is ENABLE_CACHE=0 right?

mnapoli avatar Feb 07 '25 08:02 mnapoli

That would still need to be cast to something somewhere, else you're still passing a string "0" to the service that's expecting it, which generally won't do what you intend. Since the $_ENV variable can be modified trivially by anyone, I don't think it's safe to just assume it's always going to be only-strings. Even null is a potentially conflicting sentinel value, I suppose, but less so than anything else. A dedicated enum is the only guaranteed conflict-free option.

Crell avatar Feb 07 '25 23:02 Crell

That would still need to be cast to something somewhere

Yes there's an open discussion about that topic

mnapoli avatar Feb 08 '25 10:02 mnapoli