如何使用 putenv() 更新现有环境变量?
How do I use putenv() to update existing environment variable?
编辑:据我所知,我的问题是因为 PHP 中的一个缺陷。我已将此问题复制到此处的 PHP 错误跟踪器:https://bugs.php.net/bug.php?id=74143 并计划尝试实施修复。
putenv 函数设置环境变量的值。根据手册,putenv returns 成功时为真,失败时为假。
但是,我发现 putenv 函数有时 returns 为真而不更新当前会话的环境变量。
要重现此问题,请使用 fastcgi_param 指令在使用 PHP FPM 的网络服务器中设置环境变量。这非常有用,因为它允许将环境变量设置为与同一服务器上的其他主机隔离。
示例nginx.conf:
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param TESTVAR_ENV old-value;
include fastcgi_params;
}
示例test.php:
var_dump(getenv("TESTVAR_ENV"));
var_dump(putenv("TESTVAR_ENV=new-value"));
var_dump(getenv("TESTVAR_ENV"));
test.php 的输出:
string(12) "old-value"
bool(true)
string(12) "old-value"
如您所见:
- getenv 成功读取现有值,
- putenv函数returns为真,表示成功,
- 实际上并没有设置新值,这令人难以置信。
我是不是误解了 putenv 函数的用途? setenv 手册页上是否缺少一些文档?如何使用 putenv() 更新现有环境变量?
这很有趣。经过调查,我发现 getenv()
.
有一个 undocumented parameter
按预期调用 putenv("TESTVAR_ENV=new-value")
,然后调用 getenv("TESTVAR_ENV", true)
returns new-value
。但是 getenv("TESTVAR_ENV", true)
return 在调用时未先显式设置值时为 false。
从 source 读取似乎如果 local_only 设置为 false(默认值),则使用 sapi_getenv
,而 local_only 设置为 true 则使用原生 getenv
。
此外,如果 sapi_getenv
没有 return 一个值,那么 getenv
被调用作为后备。这意味着如果您根本不在 nginx/Apache 配置中设置 TESTVAR_ENV
,putenv
/getenv
将按预期工作。
回顾一下:
getenv(name)
从 SAPI 的 (php-fpm) 内部环境 table 搜索,如果未设置变量则回退到 OS 的环境。
getenv(name, true)
仅从 OS 的环境中搜索,这不一定(取决于 SAPI)包含在网络服务器配置中注册的变量。
putenv()
总是只更新 OS 的环境。
我使用以下方法对此进行了测试:
header("Content-Type: text/plain");
dump_env();
echo 'getenv("TESTVAR_ENV") => ' .
var_export(getenv("TESTVAR_ENV"), true) . "\n";
echo 'getenv("TESTVAR_ENV", true) => ' .
var_export(getenv("TESTVAR_ENV", true), true) . "\n";
echo "-----------\n";
echo 'putenv("TESTVAR_ENV=new-value") => ' .
var_export(putenv("TESTVAR_ENV=new-value"), true) . "\n";
dump_env();
echo 'getenv("TESTVAR_ENV") => ' .
var_export(getenv("TESTVAR_ENV"), true) . "\n";
echo 'getenv("TESTVAR_ENV", true) => ' .
var_export(getenv("TESTVAR_ENV", true), true) . "\n";
function dump_env() {
echo "--- env ---\n" . `env` . "-----------\n";
}
您可以直接将新变量设置为$_ENV
或$_SERVER
:
/**
* Return specified environment variable set in `.env` file
*/
function env(string $varname = '')
{
return $varname ? $_ENV[$varname] : $_ENV;
}
/**
* Set environment variable
*/
function setenv(string $key, string $value)
{
return $_ENV[$key] = $value;
}
setenv("APP_ROOT_DIR", "YOUR_APPLICATION_ROOT_DIR"); // Sets the variable into $_ENV
echo env("APP_ROOT_DIR"); // Returns specified variable
print_r(env()); // Return the whole $_ENV array
或:
你甚至可以使用这个包:PHP Environment variables manager (php dotenv)
编辑:据我所知,我的问题是因为 PHP 中的一个缺陷。我已将此问题复制到此处的 PHP 错误跟踪器:https://bugs.php.net/bug.php?id=74143 并计划尝试实施修复。
putenv 函数设置环境变量的值。根据手册,putenv returns 成功时为真,失败时为假。
但是,我发现 putenv 函数有时 returns 为真而不更新当前会话的环境变量。
要重现此问题,请使用 fastcgi_param 指令在使用 PHP FPM 的网络服务器中设置环境变量。这非常有用,因为它允许将环境变量设置为与同一服务器上的其他主机隔离。
示例nginx.conf:
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param TESTVAR_ENV old-value;
include fastcgi_params;
}
示例test.php:
var_dump(getenv("TESTVAR_ENV"));
var_dump(putenv("TESTVAR_ENV=new-value"));
var_dump(getenv("TESTVAR_ENV"));
test.php 的输出:
string(12) "old-value"
bool(true)
string(12) "old-value"
如您所见:
- getenv 成功读取现有值,
- putenv函数returns为真,表示成功,
- 实际上并没有设置新值,这令人难以置信。
我是不是误解了 putenv 函数的用途? setenv 手册页上是否缺少一些文档?如何使用 putenv() 更新现有环境变量?
这很有趣。经过调查,我发现 getenv()
.
按预期调用 putenv("TESTVAR_ENV=new-value")
,然后调用 getenv("TESTVAR_ENV", true)
returns new-value
。但是 getenv("TESTVAR_ENV", true)
return 在调用时未先显式设置值时为 false。
从 source 读取似乎如果 local_only 设置为 false(默认值),则使用 sapi_getenv
,而 local_only 设置为 true 则使用原生 getenv
。
此外,如果 sapi_getenv
没有 return 一个值,那么 getenv
被调用作为后备。这意味着如果您根本不在 nginx/Apache 配置中设置 TESTVAR_ENV
,putenv
/getenv
将按预期工作。
回顾一下:
getenv(name)
从 SAPI 的 (php-fpm) 内部环境 table 搜索,如果未设置变量则回退到 OS 的环境。getenv(name, true)
仅从 OS 的环境中搜索,这不一定(取决于 SAPI)包含在网络服务器配置中注册的变量。putenv()
总是只更新 OS 的环境。
我使用以下方法对此进行了测试:
header("Content-Type: text/plain");
dump_env();
echo 'getenv("TESTVAR_ENV") => ' .
var_export(getenv("TESTVAR_ENV"), true) . "\n";
echo 'getenv("TESTVAR_ENV", true) => ' .
var_export(getenv("TESTVAR_ENV", true), true) . "\n";
echo "-----------\n";
echo 'putenv("TESTVAR_ENV=new-value") => ' .
var_export(putenv("TESTVAR_ENV=new-value"), true) . "\n";
dump_env();
echo 'getenv("TESTVAR_ENV") => ' .
var_export(getenv("TESTVAR_ENV"), true) . "\n";
echo 'getenv("TESTVAR_ENV", true) => ' .
var_export(getenv("TESTVAR_ENV", true), true) . "\n";
function dump_env() {
echo "--- env ---\n" . `env` . "-----------\n";
}
您可以直接将新变量设置为$_ENV
或$_SERVER
:
/**
* Return specified environment variable set in `.env` file
*/
function env(string $varname = '')
{
return $varname ? $_ENV[$varname] : $_ENV;
}
/**
* Set environment variable
*/
function setenv(string $key, string $value)
{
return $_ENV[$key] = $value;
}
setenv("APP_ROOT_DIR", "YOUR_APPLICATION_ROOT_DIR"); // Sets the variable into $_ENV
echo env("APP_ROOT_DIR"); // Returns specified variable
print_r(env()); // Return the whole $_ENV array
或:
你甚至可以使用这个包:PHP Environment variables manager (php dotenv)