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/emptygetenv() 不会发出通知。

【讨论】:

没有解释为什么 $_ENV("FOO") 和 getenv("FOO") 返回不同的结果。 新增getenv() 优点:访问前无需查看isset/emptygetenv() 不会发出通知。【参考方案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”。 所以只需:&lt;?php getenv('path') ?&gt;

【讨论】:

以上是关于PHP 中的 getenv() 与 $_ENV的主要内容,如果未能解决你的问题,请参考以下文章

Linux下获取和设置环境变量

PHP 致命错误:调用未定义函数 apache_getenv()

PHP中getenv()和$_SERVER的区别

openresty中的set_by_lua&os.getenv:alpine docker container

laravel 5.8 在 getenv 上返回 false

os.GetEnv()在设置env变量后不起作用