【问题标题】:How to change php dotenv (.env) variables dynamically in laravel or php?如何在 laravel 或 php 中动态更改 php dotenv (.env) 变量?
【发布时间】:2021-04-13 09:50:55
【问题描述】:

我想要这样的东西:

env('APP_ENV');
setenv('APP_ENV', 'testing');
env('APP_ENV');

输出:

staging
testing

我找到了一个答案How to change variables in the .env file dynamically in Laravel? 但是这里 .env 是永久保存的,我不想永久保存。 phpunit 是如何做到这一点的?因为我可以把 phpunit.xml 这个:

...
<php>
    <env name="APP_ENV" value="testing"/>
</php>
....

而 env('APP_ENV') 给了我“测试”...

【问题讨论】:

  • 为什么不直接使用 config/app.php 或 config/mynewconfigfile.php?
  • 因为如果有 20 个或更多开发人员在项目上工作,那么很有可能有人会使用 env() 或 $this->app->environment('local', 'dev') 并且应用程序将无法工作正如预期的那样......
  • @veelen 我解释了为什么不重复......
  • @fico7489 对不起,你是对的......

标签: php laravel


【解决方案1】:

putenv() 就像一个魅力:

echo env('APP_ENV');
putenv('APP_ENV=testing');
echo env('APP_ENV');

输出:

staging
testing

.env 文件未附加...

【讨论】:

  • 在 laravel 7 中这不起作用。任何人都可以向我解释为什么上面不是代码不起作用。
  • 是的,我在 laravel 7 中找到了一种方法。这对我有用 $value = config('app.name');参考laravel.com/docs/5.3/…
  • 自 Laravel 5.8 起这不起作用! Env variables became immutable 所以putenv 不会改变它们。
【解决方案2】:

Laravel .env 文件值 are read by Laravel 在应用程序启动时并存储在 PHP $_ENV global array 的相应键下。

您可以更改任何 Laravel(或其他 $_ENV)的值,如下所示:

// Assign the key's new value in the $_ENV global array
$_ENV['DB_CONNECTION'] = 'sqlite';

但是,Laravel 是否会考虑您的更改取决于您在代码中放置此作业的位置。

开发、登台、生产环境:

在内存中为这些环境动态更改 env 值是个坏主意。

尽管如此,要进行此更改,您必须在框架实例化 LoadEnvironmentVariables 类之前将您的分配放在 Laravel 引导文件中(对于 Lumen,实例化发生在 /bootstrap/app.php 文件中,对于 Laravel,您可以将您的更改放在同一个应用程序实例化之前的文件)。

测试环境

但是,对于测试环境,更改 env 变量有时会很有用。

the PHPUnit capability 之上在测试加载时更改环境变量(例如,请参阅项目文件夹中的 Laravel 的 phpunit.xml):

<php>
    <env name="DB_CONNECTION" value="sqlite"/>
</php>

您可以更改 PHPUnit's setUp function 中的变量(Laravel 中的 also bootstraps the application - 注意测试扩展了 Laravel TestCase),如下所示:

public $savedDBConnection;
public function setUp():void
{
    $this->savedDBConnection = $_ENV['DB_CONNECTION'];
    $_ENV['DB_CONNECTION'] = 'mysql';
    parent::setUp();
}

警告

通常您可能会面临这种动态变化带来的令人不快的副作用(例如,您使用内存数据库进行测试并暂时切换到磁盘测试数据库,而其他一些测试的database refresh 会擦除您的磁盘测试数据库数据)。

为避免这种情况,您必须先保存变量,然后在 setUp 方法中更改它们(如上所示)并在 tearDown method 中恢复它们,如下所示:

public function tearDown():void
{
    $_ENV['DB_CONNECTION'] = $this->savedDBConnection;
    parent::tearDown();
}

替代方案

还有另一种有时更适用的方法来更改测试环境的.env 变量(致谢here。):创建.env.testing 文件并在测试时加载它。简而言之,按照cmets中的说明添加以下colde

// Add in tests/TestCase.php::createApplication() method
// below $app = require __DIR__.'/../bootstrap/app.php' call.
if (file_exists(dirname(__DIR__) . '/.env.testing')) {
    (new \Dotenv\Dotenv(dirname(__DIR__), '.env.testing'))->load();
}

现在有足够的信息来决定是否、何时或如何需要/可以动态更改环境变量。

【讨论】:

    【解决方案3】:

    Dotenv 是不可变的,因此您无法更改已分配的值。 (https://github.com/vlucas/phpdotenv#immutability)

    PHPUnit 在启动过程中设置这个值,在 laravel 启动之前。 Laravel dotenv 以不可变模式运行,因此已经设置的值不会被覆盖。

    【讨论】:

    • 嗯,但是我想在 laravel bootstrap 期间更改 .env...为什么 phpunit 可以在 bootstrap 期间设置而 laravel 在 bootstrap 期间不能?
    【解决方案4】:

    注意:

    Laravel ~5.7:

    env('AAA') = getenv('AAA') → 要设置变量 AAA 的值,只需使用 putenv('AAA', 'true');

    → env('AAA') 将变为 TRUE

    您可以在此处查看 getenv() 的详细信息 https://github.com/laravel/framework/blob/5.7/src/Illuminate/Support/helpers.php

    Laravel 5.8~:

    从 Laravel 5.8 开始,env() 不再使用 getenv()。

    因此,env('AAA') != getenv('AAA')

    → 所以即使我们使用putenv('AAA', 'true');,env('AAA') 的值也不会改变。

    因为 env() 的行为变成了

    env('AAA') = Env::getRepository()->get('AAA');
    

    → 要设置变量 AAA 的值,请使用 Env::getRepository()-&gt;set('AAA','true') → env('AAA') 将变为 TRUE

    您可以在此处查看 Laravel 5.8 的 getenv() 的详细信息 https://github.com/laravel/framework/blob/5.8/src/Illuminate/Support/helpers.php

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-18
      • 2015-12-11
      • 2016-05-20
      • 2015-04-26
      • 2020-12-29
      相关资源
      最近更新 更多