2
votes

Can someone help explain why environment variables loaded in through Symfony's Dotenv component are sometimes not being set?

I have an PHP application that makes several concurrent local HTTP requests (essentially calling another script). Each request loads tries to load the .env file, and use its data via getenv(). During every run, some of the requests load the information fine, while others do not. It almost seems like the Dotenv library's load() method works asynchronously.

My main script pools a bunch of HTTP requests using GuzzleHttp. Inside each request, I have the following code that tries to load and access the variables:

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
    ]
);

On some requests, the values of these getenv() calls will be blank. If I re-run the script, other requests will be blank.

I tried moving the Dotenv loader calls inside the Controller method, that did not work.

I'm not sure if there is an error in my code, or I am misunderstanading how dotenv files are loaded.


Edit: System information

OS: Windows 10 x64

PHP version: 5.6.31

Configure Command:

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"

1
Code seems correct. Try logging the env values right after the load call: maybe something after load but before your controller is overwriting them. - bishop
Also make sure wjatever serves thus cide is serving from one place only: if you have multiple installs, and other installs are being offered, maybe one of those is missing its .env file - bishop
Ah, it seems you were right. I can access the variables right before the controller constructor call, but not always inside the constructor. I guess they are being overwritten. Thanks! - rideron89

1 Answers

3
votes

So it seems the issue is actually with however getenv() retrieves the variables. I switched to using $_ENV and it works everytime.

$host     = $_ENV["DB_HOST"];
$name     = $_ENV["DB_NAME"];
$user     = $_ENV["DB_USER"];
$password = $_ENV["DB_PASSWORD"];

This stackoverflow answer sheds some light on how getenv differs from $_SERVER. So my guess is that there is some disconnect with how Dotenv was saving variables, and getenv was retrieving them.