Может ли кто-нибудь помочь объяснить, почему переменные среды, загруженные через компонент Symfony Dotenv, иногда не устанавливаются?
У меня есть приложение PHP, которое выполняет несколько одновременных локальных HTTP-запросов (по сути, вызывая другой скрипт). Каждый запрос загрузки пытается загрузить файл .env и использовать его данные через getenv(). Во время каждого запуска некоторые запросы загружают информацию нормально, а другие - нет. Кажется, что метод load() библиотеки Dotenv работает асинхронно.
Мой основной скрипт объединяет кучу HTTP-запросов с помощью GuzzleHttp. Внутри каждого запроса у меня есть следующий код, который пытается загрузить и получить доступ к переменным:
index.php
require dirname(__DIR__) . '/vendor/autoload.php';
$dotenv = new \Symfony\Component\Dotenv\Dotenv();
$dotenv->load(dirname(__DIR__) . "/.env");
$instance = new App\Controllers\Controller();
Controller.php
$host = getenv("DB_HOST");
$name = getenv("DB_NAME");
$user = getenv("DB_USER");
$password = getenv("DB_PASSWORD");
$this->client = new PDO(
"mysql:host = {$host};dbname = {$name}",
$user,
$password,
[
PDO::ATTR_TIMEOUT => 600,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]
);
По некоторым запросам значения этих вызовов getenv() будут пустыми. Если я перезапущу скрипт, другие запросы будут пустыми.
Я попытался переместить вызовы загрузчика Dotenv внутри метода Controller, но это не сработало.
Я не уверен, есть ли в моем коде ошибка, или я неправильно понимаю, как загружаются файлы dotenv.
Обновлено: системная информация
ОС: Windows 10 x64
Версия PHP: 5.6.31
Настроить команду:
cscript /nologo configure.js "--enable-snapshot-build" "--disable-isapi" "--enable-debug-pack" "--without-mssql" "--without-pdo-mssql" "--without-pi3web" "--with-pdo-oci=c:\php-sdk\oracle\x86\instantclient_12_1\sdk,shared" "--with-oci8-12c=c:\php-sdk\oracle\x86\instantclient_12_1\sdk,shared" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--with-mcrypt=static" "--without-analyzer" "--with-pgo"
Также убедитесь, что wjatever обслуживает, поэтому cide обслуживается только из одного места: если у вас несколько установок и предлагаются другие установки, возможно, в одной из них отсутствует файл .env
Ах, кажется, ты был прав. Я могу получить доступ к переменным прямо перед вызовом конструктора контроллера, но не всегда внутри конструктора. Я предполагаю, что они перезаписываются. Спасибо!






Так что, похоже, проблема в том, что getenv() извлекает переменные. Я перешел на использование $_ENV, и он работает постоянно.
$host = $_ENV["DB_HOST"];
$name = $_ENV["DB_NAME"];
$user = $_ENV["DB_USER"];
$password = $_ENV["DB_PASSWORD"];
Этот ответ stackoverflow проливает свет на то, чем getenv отличается от $_SERVER. Итак, я предполагаю, что есть некоторая несогласованность с тем, как Dotenv сохранял переменные, а getenv их извлекал.
Dotenv загружает их в $_ENV, одновременно выполняя putenv.. Не могли бы вы опубликовать флаги компиляции вашей ОС, версии PHP и PHP? Поскольку это может быть ошибка движка, возможно # 74986Просто добавил его в исходный пост. Я на Win10 x64, использую PHP v5.6.31
Хорошо, я собираюсь худой в отношении ошибки с PHP 5.6 в Windows, однако: размещение в среде не всегда надежно. Чтение из $ _ENV - здесь надежное решение.
Я часами теребил волосы. Использование $ _ENV решило проблему с двумя одновременными HTTP-запросами, что привело к разным результатам.
Код кажется правильным. Попробуйте записать значения env сразу после вызова загрузки: возможно, что-то после загрузки, но до того, как ваш контроллер перезапишет их.