Dotenv требует файла .env на производстве

Я использую dotenv для PHP для управления настройками среды (не lavarel, но я отметил его, потому что lavarel также использует dotenv)

Я исключил .env из базы кода, и я добавил файл .env.example для всех других соавторов

На странице github dotenv:

phpdotenv предназначен для среды разработки и обычно не должен использоваться в производстве. В производстве фактические переменные среды должны быть установлены так, чтобы не было накладных расходов на загрузку файла .env для каждого запроса. Это может быть достигнуто с помощью автоматизированного процесса развертывания с помощью таких инструментов, как Vagrant, chef или Puppet, или может быть настроен вручную с помощью облачных узлов, таких как Pagodabox и Heroku.

То, что я не понимаю, это то, что я получаю следующее исключение:

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

Это противоречит тому, что говорит документация: "фактические переменные среды должны быть установлены так, чтобы не было накладных расходов на загрузку файла .env для каждого запроса".

Итак, вопрос в том, есть ли какая-то причина, почему dotenv выбрасывает это исключение и/или я что-то упускаю? Прежде всего, поведение отличается от других библиотек dotenv (ruby)

Я могу легко обойти это, не очень приятное решение:

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

Самое приятное решение, на мой взгляд, но я думаю, что dotenv должен справиться с этим.

$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();
}

Ответ 1

Dotenv был построен вокруг идеи, что он будет использоваться только в средах разработки. Таким образом, он всегда ожидает наличия файла .env.

Решение, которое вам не понравилось, является рекомендуемым способом использования Dotenv. И кажется, что он не изменится в ближайшем будущем. Связанная дискуссия в трекере по проблеме проекта: https://github.com/vlucas/phpdotenv/issues/63#issuecomment-74561880

Обратите внимание, что Mark предлагает хороший подход к средам производства/промежуточной загрузки, который пропускает загрузку файлов, но не проверяет

$dotenv = new Dotenv\Dotenv();
if(getenv('APP_ENV') === 'development') {
    $dotenv->load(__DIR__);
}
$dotenv->required('OTHER_VAR');

Ответ 2

Если у вас возникли проблемы с созданием переменной APP_ENV, этот код проще:

$dotenv = new Dotenv\Dotenv(__DIR__);
if(file_exists(".env")) {
    $dotenv->load();
}

Ответ 3

Также рассмотрел это, мое текущее решение - использовать Lumen way (по состоянию на 6 июня 2016 года), который был предлагается в обсуждении:

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

При необходимости вы можете выполнить некоторую дополнительную обработку исключений (например, упасть до значений по умолчанию или выполнить некоторую проверку.