Laravel - 自定义 .env 文件

11

Laravel假定.env文件应该描述环境,并且不应该提交到你的代码库中。

如果我想在我的代码库中保留devproduction两个.env文件(例如.env-production.env-dev),并添加一些自定义逻辑来确定使用哪个文件,例如基于当前域名。

类似于:

if ($_SERVER['HTTP_HOST'] == 'prod.domain.com') {
    load('.env-production');
} else {
    load('.env-dev');
}

我该如何实现它? 谢谢!

6个回答

11

Nadeem0035 给了我一个非常好的想法要做什么。

bootstrap\app.phpreturn $app; 之前。

$envFile = $_SERVER['HTTP_HOST'] == 'prod.domain.com' ? '.env-production' : '.env-dev';
$app->loadEnvironmentFrom($envFile);

8

使用Dotenv::load()加载自定义.env文件

laravel 5.1使用vlucas/phpdotenv ~1.0

if ($_SERVER['HTTP_HOST'] == 'prod.domain.com') {
    Dotenv::load(__DIR__ . '/../','.production.env');
} else {
    Dotenv::load(__DIR__ . '/../','.dev.env');
}

OR

使用vlucas/phpdotenv ~2.0与laravel 5.2

$dotenv = new Dotenv\Dotenv(__DIR__, 'myconfig'); // Laravel 5.2
$dotenv->load();

PHP dotenv

在bootstrap/app.php中


谢谢你的回答,但对我没有用 - 因为load不是一个静态方法,而且直接访问Dotenv可能不是最好的方式,但你给了我很好的想法,我想到了我的答案 - 使用$app->loadEnvironmentFrom($envFile);代替。谢谢! - SmxCde
@SmxCde 我的第一段代码是在 Laravel 5.1.* 中进行测试的,使用的是 vlucas/phpdotenv ~1.0 链接 - Nadeem0035
我想补充一下,你可以使用$app->useEnvironmentPath('/var/www/'.$_SERVER['VHOST_NAME']);指向不同的目录。这解决了我的共享代码库和不同虚拟主机的问题。然后你的VHOST配置可以有一个SetEnv ```<VirtualHost *:80> ServerName yoursub.domain.com DocumentRoot /var/www/yoursub/publicSetEnv VHOST_NAME 'yoursub'```。 - Skid Kadda

3
我可以为需要不同的事物(如数据库连接、SMTP设置等)的许多vhost共享代码库的人添加解决方案。 对于每个vhost,在Apache上创建一个vhost配置文件:
<VirtualHost *:80>
    ServerName your-vhost.yourdomain.com
    DocumentRoot /var/www/shared-codebase/public

    SetEnv VHOST_NAME 'your-vhost'

    <Directory "/var/www/shared-codebase/public">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride all
    Order deny,allow
    Require all granted
    </Directory>

    <IfModule mpm_itk_module>
       AssignUserId your-vhost your-vhost
    </IfModule>

    ErrorLog /var/www/your-vhost/logs/error.log
    CustomLog /var/www/your-vhost/logs/access.log combined
</VirtualHost>

所有虚拟主机都有相同的文档根目录和目录,因为它是共享的代码库。在配置中,我们添加了一个 SetEnv VHOST_NAME 'your-vhost',稍后我们将在 Laravel 的 bootstrap.php 中使用它来更改虚拟主机特定的 .env 的位置。
接下来,在文件夹中创建自定义的 .env 文件(例如 /var/www/your-vhost/.env),然后修改 bootstrap.php 以从正确的位置加载 .env。
<?php

$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

/*
|--------------------------------------------------------------------------
| Add the location of the custom env file
|--------------------------------------------------------------------------
*/    
$app->useEnvironmentPath('/var/www/'.$_SERVER['VHOST_NAME']);

return $app;

这就是全部内容。

[编辑] 如果你想针对特定的数据库或为特定的.env生成密钥,那么你应该在artisan命令前面放置VHOST_NAME。

VHOST_NAME=tenant2.domain.com php artisan key:generate

[编辑] 当您在本地工作并使用Laravel Valet时,可以在代码库的根目录中添加自定义.valet-env.php。详情请参考:https://laravel.com/docs/master/valet#site-specific-environment-variables


使用 $app->useEnvironmentPath(); 正确地通知 Laravel 新的 .env 文件位置,可以获得 +1 分。其他解决方案会重载 Dotenv\Dotenv,如果你正在运行 artisan key:generate,可能会带来问题。 - Ifnot

1
你已经将单个.env文件添加到Laravel中,并且可以定义应用程序的级别。 APP_ENV=local 或者 APP_ENV=production 您可以根据需要设置配置,无需创建新的.env文件。有关更多信息,请参见Laravel环境变量:并且这里有更详细的帮助phpdotenv

谢谢您的回答,但这不是我想要的:我仍然想使用.env文件,因为它很方便,但我不想在小型个人项目中使用不必要的繁文缛节和过度安全措施,而且我也是唯一的维护者。默认提供的架构很好,但对于较小的项目来说需要付出太多的努力。 - SmxCde

1
我在开发过程中有类似的需求,希望能够在我的开发环境中进行一些即兴的“多租户”测试,以测试相同的代码库针对多个数据库/配置的情况。我不想要一堆 if/then 语句的混乱代码,因此我想出了以下解决方案,它非常适合我的目的(并且不需要修改 Apache、nginx 或 Caddy 文件):
bootstrap/app.php 文件中,在 $app = new Illuminate\Foundation\Application(...); 行后面添加以下内容:
// First, check to see if there is a file named '.env'
// within a subdirectory named '.env.{{HOST_NAME}}
//
if (is_file($app->environmentPath().DIRECTORY_SEPARATOR. '.env.' . $_SERVER['HTTP_HOST'] .DIRECTORY_SEPARATOR. '.env')) {

    // ...And if there is, use the directory as the new environment path
    $app->useEnvironmentPath($app->environmentPath().DIRECTORY_SEPARATOR. '.env.'. $_SERVER['HTTP_HOST']);
}ER['HTTP_HOST']);
}

// Otherwise,  just use the standard .env file as the default...

一旦包含此内容,应用程序仍将默认使用.env(这意味着您仍然可以为不需要自定义的任何主机使用标准的.env文件),但是首先它会检查是否存在一个名为主机名的子目录中的替代.env文件(即,如果主机名是“example.local.com”,则该文件将驻留在名为.env.example.local.com的子目录中)。
您可以更改代码以删除有些冗余的.env.前缀,但我喜欢添加它以便在目录列表中将所有.env.*条目放在一起。
这种方法的一个额外好处是:通过在子目录中使用通常名称(“.env”),您只需要一个.env条目就可以确保所有自定义配置都不会进入git repo。无需为每个自定义点环境文件添加新的.gitignore条目。

0

我想分享一下我的看法,对于在不同机器/主机上工作的团队。

我在应用程序的根目录下创建了一个名为env的目录,其中包含:

  • 一个.master.env文件,其中包含主要和共享配置。
  • 一个.name文件,仅包含特定机器/目的环境的名称字符串(例如“server1”)。
  • 与上述定义的名称匹配的特定.env文件,例如.server1.env

然后,在bootstrap/app.php中:

/**
 * master config
 */
$app->useEnvironmentPath(__DIR__.'/../env');
$app->loadEnvironmentFrom('.master.env');

/**
 * config overloading
 */
$app->afterLoadingEnvironment(function() use($app) {
    $envFile = trim(file_get_contents($app->environmentPath().'/.name'));
    if ($envFile && file_exists($app->environmentPath().'/.' .$envFile .'.env')) {
        $dotenv = Dotenv\Dotenv::create($app->environmentPath(), '.'.$envFile.'.env');
        $dotenv->overload();
    }
});

现在,您可以有选择地覆盖特定机器的配置键,如果您没有安全问题,可以将env文件放入VCS中,只要忽略`.name'文件。

适用于Laravel 5.8。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接