getenv () против $ _ENV в PHP

88

В чем разница между getenv()и $_ENV?

Есть ли компромиссы между их использованием?

Я заметил, что иногда getenv()дает мне то, что мне нужно, а $_ENVне дает (например HOME).

тау
источник
1
Не попадайтесь в ловушку, когда PHP скрывает от вас кровавые подробности. $_ENVи $_SERVERзаполняются данными, полученными различными способами. getenv()это еще один способ доступа к данным, к которым PHP не позволяет получить доступ напрямую. Работает даже variables_order = "G"при пустых $_SERVERи $_ENVпустых. Прочтите отличный ответ Конора Макдермотроу .
Palec
Для тех, кто использует фреймворк Symfony, есть еще один ограниченный случай из вышеперечисленного. getenv () всегда будет возвращать значение переменной env, как это было при запуске php-сервера, даже если впоследствии оно было изменено. В то время как $ _ENV [] можно изменить во время выполнения, изменив файлы .env. Но, конечно, это относится к Symfony, а не к PHP в целом.
Росс Иванцив

Ответы:

59

Согласно документации php о getenv , они точно такие же, за исключением того, что они getenvбудут искать переменную без учета регистра. В большинстве случаев это, вероятно, не имеет значения, но один из комментариев к документации объясняет:

Например, в Windows $ _SERVER ['Path'] выглядит так, как вы видите, с заглавной первой буквой, а не 'PATH', как вы могли ожидать.

Из-за этого я, вероятно, предпочел бы использовать, getenvесли вы не уверены в регистре заголовка переменной, которую вы пытаетесь получить.

Баткинс
источник
15
Не объясняет, почему $ _ENV ("FOO") и getenv ("FOO") возвращают разные результаты.
Rich Remer
Дополнительное getenv()преимущество: вам не нужно проверять isset/ emptyперед доступом. getenv()не будет отправлять уведомления.
Стив Клэй,
53

Я знаю, что комментарий в документах говорит, что 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

Глядя на исходный код для getenvфункции, это происходит потому , что есть три способа , что PHP может принести переменную окружения:

  1. Через sapi_getenv(например, если он получает переменную среды из Apache)
  2. Если в Windows, из GetEnvironmentVariableA.
  3. Если не в Windows, из getenvфункции, предоставляемой libc.

Насколько я могу судить, единственный случай, когда он будет вести себя без учета регистра, - это Windows, потому что именно так ведет себя API переменных среды Windows. Если вы используете Linux, BSD, Mac и т. Д., То getenvвсе равно регистр учитывается.

Как упоминал Марио , $_ENVне всегда заполняется из-за различных конфигураций, variables_orderпоэтому лучше избегать, $_ENVесли вы не контролируете конфигурацию сервера.

Итак, для наиболее переносимого PHP-кода:

  1. Используйте getenv.
  2. Используйте правильный регистр для имени переменной среды.
Конор Макдермотро
источник
36

Дополнительно $_ENVобычно пусто, если variables_orderего нет в Eсписке. Во многих настройках вполне вероятно, что он только $_SERVERзаполнен и $_ENVпредназначен исключительно для использования через CLI.

С другой стороны, имеет getenv()прямой доступ к среде.

(Что касается двусмысленности падежа, можно было бы проще использовать array_change_key_case().)

Марио
источник
6

Я счел getenv()полезным избежать странной ошибки PHP, когда иногда $_SERVERи $_ENVбыло неопределенным, если auto_globals_jitбыло включено (создание переменных _SERVER и _ENV при их первом использовании). С тех пор я стал им пользоваться.

Леопольдо Санчик
источник
3

Взято из документации PHP :

Эта функция полезна (по сравнению с $_SERVER, $_ENV), потому что она ищет ключ $ varname в этом массиве без учета регистра. Например, в Windows $_SERVER['Path']вы видите заглавные буквы, а не « PATH», как вы ожидали. Так что просто:<?php getenv('path') ?>

Айман Сафади
источник
3

Я бы добавил, что getenv () - лучший выбор, потому что в качестве функции ее можно перегрузить для целей тестирования. В то время как перезапись переменных $ _SERVER или $ _ENV может помешать работе тестовых фреймворков и других библиотек и, в конечном итоге, потребует гораздо больше работы для безопасного выполнения.

Джо Грин
источник
0

читать env и создавать

<?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);
    }
}
?>
neoistone inc.
источник