getenv () kontra $ _ENV w PHP

88

Jaka jest różnica między getenv()i $_ENV?

Czy są jakieś kompromisy między używaniem któregokolwiek z nich?

Zauważyłem, że czasami getenv()daje mi to, czego potrzebuję, a $_ENVnie (np. HOME).

tau
źródło
1
Nie daj się złapać w pułapkę PHP ukrywającego przed Tobą krwawe szczegóły. $_ENVi $_SERVERsą wypełnione danymi uzyskanymi na różne sposoby. getenv()to kolejny sposób uzyskiwania dostępu do danych, do których PHP nie umożliwia bezpośredniego dostępu. Działa nawet z variables_order = "G", kiedy $_SERVERi $_ENVsą puste. Przeczytaj świetną odpowiedź Conora McDermottroe .
Palec
Dla tych, którzy używają frameworka Symfony, jest jeszcze jeden ograniczony przypadek powyższego. getenv () zawsze zwraca wartość zmiennej env, taką jaka była podczas uruchamiania serwera php, nawet jeśli później została zmieniona. Natomiast $ _ENV [] można zmienić w czasie wykonywania, modyfikując pliki .env. Ale oczywiście dotyczy to Symfony, a nie ogólnie PHP.
Ross Ivantsiv

Odpowiedzi:

59

Zgodnie z dokumentacją php dotyczącą getenv , są one dokładnie takie same, z tym wyjątkiem, że getenvbędą szukać zmiennej bez rozróżniania wielkości liter. W większości przypadków prawdopodobnie nie ma to znaczenia, ale jeden z komentarzy do dokumentacji wyjaśnia:

Na przykład w systemie Windows $ _SERVER ['Path'] jest jak widać, z pierwszą literą wielką, a nie 'PATH', jak można by się spodziewać.

Z tego powodu prawdopodobnie zdecydowałbym się użyć, getenvchyba że masz pewność co do wielkości liter w tytule zmiennej, którą próbujesz pobrać.

Batkins
źródło
15
Nie wyjaśnia, dlaczego zmienne $ _ENV ("FOO") i getenv ("FOO") zwracają różne wyniki.
bogate wspomnienie
Dodatkowa getenv()zaleta: nie musisz sprawdzać isset/ emptyprzed dostępem. getenv()nie będzie emitować powiadomień.
Steve Clay
53

Wiem, że komentarz w dokumentacji mówi, że wielkość getenvliter nie jest rozróżniana, ale to nie jest zachowanie, które widzę:

> 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

Patrząc na kod źródłowy dla getenvfunkcji, to dlatego, że istnieją trzy sposoby, że PHP może pobrać zmienną środowiskową:

  1. Przez sapi_getenv(np. Jeśli pobiera zmienną środowiskową z Apache)
  2. Jeśli w systemie Windows, z GetEnvironmentVariableA.
  3. Jeśli używasz systemu innego niż Windows, z getenvfunkcji dostarczonej przez libc.

O ile wiem, jedyny moment, w którym zachowuje się bez rozróżniania wielkości liter, występuje w systemie Windows, ponieważ tak zachowuje się zmienna środowiskowa Windows API. Jeśli używasz Linuksa, BSD, Maca itp., getenvNadal jest rozróżniana wielkość liter.

Jak wspomniano w mario , $_ENVnie zawsze jest wypełniony ze względu na różne konfiguracje, variables_orderwięc najlepiej tego unikać, $_ENVjeśli nie kontrolujesz konfiguracji serwera.

Tak więc dla najbardziej przenośnego kodu PHP:

  1. Użyj getenv.
  2. Użyj poprawnej wielkości liter dla nazwy zmiennej środowiskowej.
Conor McDermottroe
źródło
36

Dodatkowo $_ENVjest zwykle pusty, jeśli variables_ordernie ma na Eliście. W wielu konfiguracjach jest prawdopodobne, że $_SERVERjest wypełniony tylko i $_ENVjest przeznaczony wyłącznie do użytku z interfejsem CLI.

Z drugiej strony getenv()ma bezpośredni dostęp do środowiska.

(Jeśli chodzi o niejednoznaczność przypadku, można prościej zastosować array_change_key_case().)

mario
źródło
6

Znalazłem getenv()przydatna uniknąć dziwny PHP bug gdzie czasem $_SERVERi $_ENVzostała zdefiniowana jeśli auto_globals_jitzostała włączona (tworzenie _SERVER i _ENV zmienne kiedy jesteś po raz pierwszy użyty). Od tego czasu zacząłem go używać.

Leopoldo Sanczyk
źródło
3

Zaczerpnięte z dokumentacji PHP :

Ta funkcja jest użyteczna (w porównaniu do $_SERVER, $_ENV), ponieważ przeszukuje klucz $ varname w sposób bez uwzględniania wielkości liter. Na przykład w systemie Windows $_SERVER['Path']wygląda tak, jakbyś widział wielkie litery, a nie „ PATH”, jak się spodziewałeś. Więc tylko:<?php getenv('path') ?>

Ayman Safadi
źródło
3

Dodam, że getenv () jest lepszym wyborem, ponieważ jako funkcja może być przeciążona do celów testowych. Podczas gdy nadpisywanie zmiennych $ _SERVER lub $ _ENV może kolidować z frameworkami testowymi i innymi bibliotekami i ostatecznie wymagać dużo więcej pracy, aby je bezpiecznie przeprowadzić.

Joe Green
źródło
0

przeczytaj env i utwórz

<?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.
źródło