PHP 中的 getenv() 与 $_ENV
Posted
技术标签:
【中文标题】PHP 中的 getenv() 与 $_ENV【英文标题】:getenv() vs. $_ENV in PHP 【发布时间】:2012-02-06 13:41:47 【问题描述】:getenv()
和 $_ENV
有什么区别?
使用两者之间有什么权衡吗?
我注意到有时getenv()
可以满足我的需求,而$_ENV
却不能(例如HOME
)。
【问题讨论】:
不要被 php 所困,隐藏血腥细节。$_ENV
和 $_SERVER
填充有以各种方式获得的数据。 getenv()
是另一种访问 PHP 无法直接访问的数据的方法。当$_SERVER
和$_ENV
为空时,它甚至适用于variables_order = "G"
。阅读Conor McDermottroe 的精彩回答。
相关:Why is my $_ENV empty?
对于那些使用 Symfony 框架的人来说,上面还有一个有限的案例。 getenv() 将始终返回 env 变量的值,就像 php 服务器启动时一样,即使之后它被更改。而 $_ENV[] 可以通过修改 .env 文件在运行时更改。但当然它与 Symfony 相关,而不是一般的 PHP。
【参考方案1】:
我知道文档中的评论说 getenv
不区分大小写,但 不是我看到的行为:
> 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
看the source code的getenv
函数,这是因为PHP可以通过三种方式获取环境变量:
-
通过
sapi_getenv
(例如,如果它从 Apache 获取环境变量)
如果在 Windows 上,来自GetEnvironmentVariableA
。
如果在非 Windows 上,通过 libc
提供的 getenv
函数。
据我所知,它以不区分大小写的方式运行的唯一时间是在 Windows 上,因为这就是 Windows 环境变量 API 的行为方式。如果您使用的是 Linux、BSD、Mac 等,那么getenv
仍然区分大小写。
正如mario 所述,由于variables_order
的配置不同,$_ENV
并不总是被填充,因此如果您不控制服务器配置,最好避免使用$_ENV
。
所以,对于最便携的 PHP 代码:
-
使用
getenv
。
使用正确的环境变量名称大小写。
【讨论】:
【参考方案2】:另外,如果variables_order
没有列出E
,$_ENV
通常为空。在许多设置中,很可能只填充了 $_SERVER
,而 $_ENV
仅用于 CLI。
另一方面,getenv()
直接访问环境。
(关于大小写模糊,可以更简单地使用array_change_key_case()
。)
【讨论】:
【参考方案3】:根据the php documentation about getenv,它们完全相同,只是getenv
在不区分大小写的文件系统(如Windows)上运行时会以不区分大小写的方式查找变量。在 Linux 主机上,它仍然区分大小写。大多数时候这可能无关紧要,但文档中的一个 cmets 解释说:
例如在 Windows 上 $_SERVER['Path'] 就像你看到的那样,第一个字母大写,而不是你所期望的 'PATH'。
因此,我可能会选择使用getenv
来改善跨平台行为,除非您确定要检索的环境变量的大小写。
Steve Clay 在这个答案中的评论突出了另一个区别:
新增
getenv()
优点:访问前无需勾选isset
/empty
。getenv()
不会发出通知。
【讨论】:
没有解释为什么 $_ENV("FOO") 和 getenv("FOO") 返回不同的结果。 新增getenv()
优点:访问前无需查看isset
/empty
。 getenv()
不会发出通知。【参考方案4】:
读取环境并创建
<?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);
?>
【讨论】:
这与实际问题有什么关系?【参考方案5】:我要补充一点,getenv() 是一个更好的选择,因为作为一个函数,它可以被重载以用于测试目的。而覆盖 $_SERVER 或 $_ENV 变量可能会干扰测试框架和其他库,最终需要更多的工作才能安全地执行。
【讨论】:
【参考方案6】:我发现getenv()
有助于避免 strange PHP bug,如果启用了 auto_globals_jit
(创建 _SERVER 和 _ENV em> 变量首次使用时)。从那以后我开始使用它。
【讨论】:
【参考方案7】:取自PHP docs:
此函数很有用(与
$_SERVER
、$_ENV
相比),因为它以不区分大小写的方式搜索 $varname 键。 例如,在 Windows 上,$_SERVER['Path']
就像您看到的大写字母,而不是您预期的“PATH
”。 所以只需:<?php getenv('path') ?>
【讨论】:
以上是关于PHP 中的 getenv() 与 $_ENV的主要内容,如果未能解决你的问题,请参考以下文章
PHP 致命错误:调用未定义函数 apache_getenv()
openresty中的set_by_lua&os.getenv:alpine docker container