2017-02-21 41 views
8

Edycja: o ile mogę powiedzieć, moje pytanie dotyczy wady PHP. Skopiowałem to pytanie do śledzenia błędów PHP tutaj: https://bugs.php.net/bug.php?id=74143 i planuję wypróbować i zaimplementować poprawkę.Jak używać putenv() do aktualizacji istniejącej zmiennej środowiskowej?


Funkcja putenv ustawia wartość zmiennej środowiskowej. Zgodnie z instrukcją, putenv zwraca wartość true w przypadku sukcesu, false w przypadku niepowodzenia.

Jednak stwierdzam, że funkcja putenv czasami zwraca wartość true bez aktualizacji zmiennej środowiskowej dla bieżącej sesji.

Aby odtworzyć ten problem, ustaw zmienną środowiskową na serwerze internetowym za pomocą PHP FPM, korzystając z dyrektywy fastcgi_param. Jest to niezwykle przydatne, ponieważ pozwala na ustawienie zmiennych środowiskowych w izolacji na inne hosty na tym samym serwerze.

Przykład nginx.conf:

location ~ \.php$ { 
     fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; 
     fastcgi_param TESTVAR_ENV  old-value; 
     include   fastcgi_params; 
} 

Przykład test.php:

var_dump(getenv("TESTVAR_ENV")); 
var_dump(putenv("TESTVAR_ENV=new-value")); 
var_dump(getenv("TESTVAR_ENV")); 

wyjściowe test.php:

string(12) "old-value" 
bool(true) 
string(12) "old-value" 

Jak widać:

  1. Istniejąca wartość jest odczytywana przez getenv z powodzeniem,
  2. Funkcja putenv zwraca wartość true, oznaczającą powodzenie,
  3. nowa wartość nie jest ustawiona, co jest niewiarygodne.

Czy nie rozumiem, jaki jest cel funkcji putenv? Czy jest jakiś brakujący dokument na stronie podręcznika setenv? Jak używać putenv() do aktualizacji istniejącej zmiennej środowiskowej?

+0

Nie widziałem tego zachowania się. Czy próbowałeś najpierw usunąć starą wartość? 'putenv (" TESTVAR_ENV ")' powinno wyczyścić wartość, a może spróbować użyć '$ _SERVER' zamiast tego? – miken32

+1

Właściwie to po prostu przetestowałem to z Nginx i PHP-FPM, zamiast CLI i widzę to samo. – miken32

+0

Czy uważasz, że jest to błąd w PHP lub PHP-FPM? – Greg

Odpowiedz

2

To jest interesujące. Po zbadaniu okazało się, że istnieje undocumented parameter dla getenv().

Wywołanie putenv("TESTVAR_ENV=new-value"), po którym następuje getenv("TESTVAR_ENV", true), zgodnie z oczekiwaniami, zwraca new-value. Jednak getenv("TESTVAR_ENV", true) zwraca wartość false po wywołaniu bez jawnego ustawienia wartości jako pierwszej.

Czytanie z source wydaje się, że jeśli local_only jest ustawiona na false (domyślnie), wartość jest pobierany z wykorzystaniem sapi_getenv, natomiast z local_only ustawiona na true rodzimej getenv służy.

Ponadto, jeśli sapi_getenv nie zwraca wartości, to jako rezerwowy jest wywoływany getenv. Znaczenie: jeśli nie ustawisz TESTVAR_ENV w ogóle w konfiguracji nginx/Apache, putenv/getenv działa zgodnie z oczekiwaniami.

Przypomnę więc:

  • getenv(name) wyszukiwania z SAPI za (PHP-FPM) Tabela środowisko wewnętrzne i fallbacks do środowiska systemu operacyjnego, jeśli zmienna nie jest ustawiona.
  • getenv(name, true) wyszukuje tylko ze środowiska systemu operacyjnego, które niekoniecznie (w zależności od SAPI) zawiera zmienne zarejestrowane w konfiguracji serwera WWW.
  • putenv() zawsze aktualizuje tylko środowisko systemu operacyjnego.

użyłem następujących przetestować to:

header("Content-Type: text/plain"); 

dump_env(); 
echo 'getenv("TESTVAR_ENV") => ' . 
    var_export(getenv("TESTVAR_ENV"), true) . "\n"; 
echo 'getenv("TESTVAR_ENV", true) => ' . 
    var_export(getenv("TESTVAR_ENV", true), true) . "\n"; 
echo "-----------\n"; 
echo 'putenv("TESTVAR_ENV=new-value") => ' . 
    var_export(putenv("TESTVAR_ENV=new-value"), true) . "\n"; 
dump_env(); 
echo 'getenv("TESTVAR_ENV") => ' . 
    var_export(getenv("TESTVAR_ENV"), true) . "\n"; 
echo 'getenv("TESTVAR_ENV", true) => ' . 
    var_export(getenv("TESTVAR_ENV", true), true) . "\n"; 

function dump_env() { 
    echo "--- env ---\n" . `env` . "-----------\n"; 
} 
+0

Dzięki za twój wkład w tej sprawie. Zaktualizowałem dokumentację na php.net, aby odzwierciedlić to zachowanie, chociaż nadal uważam, że można nieco poprawić jego funkcjonalność. – Greg