2017-02-21 46 views
8

Chỉnh sửa: theo như tôi có thể nói, câu hỏi của tôi là do lỗi trong PHP. Tôi đã sao chép câu hỏi này vào trình theo dõi lỗi PHP tại đây: https://bugs.php.net/bug.php?id=74143 và có kế hoạch thử và triển khai bản sửa lỗi.Làm cách nào để sử dụng putenv() để cập nhật biến môi trường hiện tại?


Hàm putenv đặt giá trị của biến môi trường. Theo hướng dẫn, putenv trả về sự thật về thành công, sai về thất bại.

Tuy nhiên, tôi thấy rằng hàm putenv đôi khi trả về true mà không cập nhật biến môi trường cho phiên hiện tại.

Để tạo lại vấn đề này, hãy đặt biến môi trường trong máy chủ web bằng cách sử dụng PHP FPM, bằng cách sử dụng chỉ thị fastcgi_param. Điều này cực kỳ hữu ích, vì nó cho phép thiết lập các biến môi trường trong sự cô lập với các máy chủ khác trên cùng một máy chủ.

Ví dụ nginx.conf:

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

Ví dụ test.php:

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

Sản lượng test.php:

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

Như bạn có thể thấy:

  1. giá trị hiện tại được đọc bởi getenv thành công,
  2. hàm putenv trả về true, cho biết thành công,
  3. giá trị mới không thực sự được đặt, điều này vô cùng khó hiểu.

Tôi có hiểu lầm về mục đích của hàm putenv không? Có một số tài liệu bị thiếu trên trang hướng dẫn cài đặt không? Làm thế nào để sử dụng putenv() để cập nhật biến môi trường hiện tại?

+0

Tôi đã không nhìn thấy hành vi này bản thân mình. Trước tiên bạn đã thử xóa giá trị cũ chưa? 'putenv (" TESTVAR_ENV ")' nên xóa giá trị, hoặc có thể thử sử dụng '$ _SERVER' thay thế? – miken32

+1

Trên thực tế, chỉ cần thử nghiệm này với Nginx và PHP-FPM, thay vì CLI và tôi nhìn thấy điều tương tự. – miken32

+0

Bạn có nghĩ đây là lỗi với PHP hay PHP-FPM không? – Greg

Trả lời

2

Điều này thật thú vị. Sau khi điều tra, tôi thấy rằng có undocumented parameter cho getenv().

Gọi putenv("TESTVAR_ENV=new-value") theo sau là getenv("TESTVAR_ENV", true) trả về new-value như mong đợi. Tuy nhiên getenv("TESTVAR_ENV", true) trả về false khi được gọi mà không đặt giá trị trước tiên một cách rõ ràng.

Đọc từ source có vẻ như rằng nếu local_only được thiết lập để sai (mặc định), giá trị được nạp bằng sapi_getenv, trong khi với local_only set là true bản địa getenv được sử dụng.

Hơn nữa, nếu sapi_getenv không trả lại giá trị, thì getenv được gọi là dự phòng. Có nghĩa là nếu bạn không đặt TESTVAR_ENV trong cấu hình nginx/Apache, thì putenv/getenv sẽ hoạt động như mong đợi.

Vì vậy, để tóm tắt:

  • getenv(name) tìm kiếm từ SAPI của (php-fpm) Bảng môi trường nội bộ, và fallbacks với môi trường hệ điều hành nếu biến không được thiết lập.
  • getenv(name, true) tìm kiếm chỉ từ môi trường của hệ điều hành, không nhất thiết (tùy thuộc vào SAPI) chứa biến được đăng ký trong cấu hình của máy chủ web.
  • putenv() luôn chỉ cập nhật môi trường của hệ điều hành.

tôi đã sử dụng sau đây để kiểm tra điều này:

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

Cảm ơn bạn đã nhập thông tin này. Tôi đã cập nhật các tài liệu trên php.net để phản ánh hành vi này, mặc dù tôi vẫn nghĩ rằng các chức năng có thể được cải thiện một chút. – Greg

Các vấn đề liên quan