【问题标题】:getenv() vs. $_ENV in PHPPHP 中的 getenv() 与 $_ENV
【发布时间】:2012-02-06 13:41:47
【问题描述】:

getenv()$_ENV 有什么区别?

使用两者之间有什么权衡吗?

我注意到有时getenv() 可以满足我的需求,而$_ENV 却不能(例如HOME)。

【问题讨论】:

  • 不要被 PHP 所困,隐藏血腥细节。 $_ENV$_SERVER 填充有以各种方式获得的数据。 getenv() 是另一种访问 PHP 无法直接访问的数据的方法。当$_SERVER$_ENV 为空时,它甚至适用于variables_order = "G"。阅读Conor McDermottroe 的精彩回答。
  • 对于那些使用 Symfony 框架的人来说,上面还有一个有限的案例。 getenv() 将始终返回 env 变量的值,就像 php 服务器启动时一样,即使之后它被更改。而 $_ENV[] 可以通过修改 .env 文件在运行时更改。但当然它与 Symfony 相关,而不是一般的 PHP。

标签: php environment-variables


【解决方案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 codegetenv函数,这是因为PHP可以通过三种方式获取环境变量:

  1. 通过sapi_getenv(例如,如果它从 Apache 获取环境变量)
  2. 如果在 Windows 上,来自GetEnvironmentVariableA
  3. 如果在非 Windows 上,通过 libc 提供的 getenv 函数。

据我所知,它以不区分大小写的方式运行的唯一时间是在 Windows 上,因为这就是 Windows 环境变量 API 的行为方式。如果您使用的是 Linux、BSD、Mac 等,那么getenv 仍然区分大小写。

正如mario 所述,由于variables_order 的配置不同,$_ENV 并不总是被填充,因此如果您不控制服务器配置,最好避免使用$_ENV

所以,对于最便携的 PHP 代码:

  1. 使用getenv
  2. 使用正确的环境变量名称大小写。

【讨论】:

    【解决方案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;

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-08-29
            • 2012-03-26
            • 1970-01-01
            • 2020-12-27
            • 1970-01-01
            • 2012-01-23
            相关资源
            最近更新 更多