dotenv requires .env file on production
Asked Answered
P

3

13

I'm using dotenv for PHP to manage the environment settings (not lavarel but I tagged it because lavarel also uses dotenv)

I have excluded the .env from the code base and I have added the .env.example for all other collaborators

On the github page of dotenv:

phpdotenv is made for development environments, and generally should not be used in production. In production, the actual environment variables should be set so that there is no overhead of loading the .env file on each request. This can be achieved via an automated deployment process with tools like Vagrant, chef, or Puppet, or can be set manually with cloud hosts like Pagodabox and Heroku.

The thing that I don't understand is that I get the following exception:

PHP Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Dotenv: Environment file .env not found or not readable.

This contradicts with what documentation says "the actual environment variables should be set so that there is no overhead of loading the .env file on each request."

So the question is if there's any reason why dotenv throws that exception and/or am I missing something? First of all the behavior is different compared to other dotenv libraries (ruby)

I can easily work around this, the not so nice solution:

if(getenv('APPLICATION_ENV') !== 'production') { /* or staging */
    $dotenv = new Dotenv\Dotenv(__DIR__);
    $dotenv->load();
}

Nicest solution in my opinion, but I think dotenv should handle this.

$dotenv = new Dotenv\Dotenv(__DIR__);
//Check if file exists the same way as dotenv does it
//See classes DotEnv\DotEnv and DotEnv\Loader
//$filePath = $dotenv->getFilePath(__DIR__); 
//This method is protected so extract code from method (see below)

$filePath = rtrim(__DIR__, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR . '.env';
//both calls are cached so (almost) no performance loss
if(is_file($filePath) && is_readable($filePath)) {
    $dotenv->load();
}
Philosophical answered 4/6, 2015 at 13:37 Comment(1)
If you don't use .env on the production server, how do you get your environment variables setup then?Alter
A
14

Dotenv was built around an idea, that it will be used in development environments only. Thus, it always expects .env file to be present.

The solution you didn't like is a recommended way to use Dotenv. And it seems, that it won't change in near future. Related discussion in project's issue tracker: https://github.com/vlucas/phpdotenv/issues/63#issuecomment-74561880

Note, that Mark offers there a good approach for production/staging environments, which skips file loading, but not validation

$dotenv = new Dotenv\Dotenv();
if(getenv('APP_ENV') === 'development') {
    $dotenv->load(__DIR__);
}
$dotenv->required('OTHER_VAR');
Affectionate answered 4/6, 2015 at 15:19 Comment(4)
Aaah I can use $dotenv->required() it works any way which is nice. The getenv('APP_ENV'); is safer i guess? I think i go for the filecheck that will be fine for the current project. Thanks!Philosophical
@SanderVisser what did you mean by saying, that getenv('APP_ENV') is safer?Affectionate
It prevents loading the .env file on a production environment even if it's there.Philosophical
When I think about. The development environment is build with vagrant and puppet, so some reasonable development defaults could be used to skip the one-time step for dotenv. That's why i choose the file check approach. but it isn't a big deal to combine both approachesPhilosophical
D
3

If you have problem to create an APP_ENV variable, this code is easier :

$dotenv = new Dotenv\Dotenv(__DIR__);
if(file_exists(".env")) {
    $dotenv->load();
}
Didst answered 18/4, 2016 at 20:47 Comment(0)
C
2

Also looked into this, my current solution is to use Lumen's way (as of 6 June 2016) which was suggested in a discussion:

try {
    (new Dotenv\Dotenv(__DIR__.'/../'))->load();
} catch (Dotenv\Exception\InvalidPathException $e) {
    //
}

You can still do some additional exception handling if needed (e.g. fall to default values or do some validation.

Correna answered 6/6, 2016 at 13:48 Comment(2)
This defeats the purpose of "no overhead of loading the .env file on each request"Mighty
@MassimilianoArione Using DotEnv at all incurs the overhead of loading the .env file on every request, so your comment actually applies to the entire premise of using DotEnv, and not just this Answer.Frosted

© 2022 - 2024 — McMap. All rights reserved.