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", як можна було очікувати.

Через це я, мабуть, вирішив би використовувати, getenvякщо ви не впевнені в регістрі заголовка змінної, яку ви намагаєтесь отримати.


15
Не пояснює, чому $ _ENV ("FOO") і getenv ("FOO") повертають різні результати.
Багатий Ремер

Додана 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це все одно чує регістр.

Як згадував mario , $_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);
    }
}
?>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.