Laravel 环境变量(没有在方法中传递默认值)在 Artisan 命令文件中不起作用

Posted

技术标签:

【中文标题】Laravel 环境变量(没有在方法中传递默认值)在 Artisan 命令文件中不起作用【英文标题】:Laravel Environment Variables(without default value passed in method) not working inside Artisan Command file 【发布时间】:2020-10-30 08:59:26 【问题描述】:

我在客户项目中使用 Laravel 6.x,其中我在 Artisan Command 中构建了一个用于同步数据的 API。

现在客户希望配置谨慎,远离主要源代码,并且尽可能没有任何后备值。这意味着我必须在.env 文件中定义配置,并使用env() 方法而不使用任何回退默认值。

这在 Laravel Artisan 命令类文件中必须是可能的,但是当我在如下代码中使用 env 方法时,它无法按预期工作:

[站点根目录]\.env:

APP_ENV=local

[站点根目录]\app\Console\Commands\SyncSomeData.php

use Illuminate\Console\Command;

class SyncSomeData extends Command

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'sync:some-data';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    
        parent::__construct();
    

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    
        exit(env('APP_ENV','staging1'));
    

这总是在控制台中打印staging1,如果我使用它而不是给定的env 方法,那么它什么也不打印:

exit(env('APP_ENV'));

据我所知并且可以相信 Laravel 是最安全的,必须有办法让 env 方法在命令文件中没有后备值的情况下工作,有人可以帮助实现这一点吗?

【问题讨论】:

你能试试 config('app.env') 吗?并先运行 php artisan config:cache ?我相信较新版本的 laravel,这是推荐的方法,我认为您无法像以前那样访问 env()。 哇,这确实有效,尽管没想到。您能否将其格式化为带有一些额外信息和参考以查找的答案以及我们需要 config 而不是 env 的原因?因为其他 SO 链接不足以很好地指导这个特定主题......欣赏它...... 我的评论并不完全正确,但我怀疑这是问题所在。我会在下面的答案中尽力而为。 另外,如果我定义了我的自定义 env 变量,如 API_SOAP_URL,我该如何打印这些变量。我刚刚尝试使用config('api.soap.url'),但打印的空白......所以请把它也包含在你的答案中,谢谢......我现在每次更改.env 文件时都会清除缓存,所以这主要不是问题...... . 如果我的答案缺少任何内容,请告诉我。您的最后一条评论可能来自添加或修改值后未运行 php artisan config:cache。 【参考方案1】:

这个答案有几个部分。

    缓存配置

仅当您在本地环境中缓存了配置时,才会出现此问题中的问题。如果你曾经运行过php artisan config:cachephp artisan optimize,那么你已经缓存了你的配置。

因此,laravel 将不再读取您的 .env 文件并从缓存中加载 config 和 .env 的所有值。

最好不要在整个应用程序中使用 env() 而是为这些值创建配置文件。这将是speed up your application in production。如果你想利用配置缓存,除了配置文件之外,你不能在任何地方使用 env()。

在您的本地环境中,文档建议您不要缓存配置,因为它会经常更新。我认为这是一个很好的建议,但有一个警告:env()。如果您没有在本地缓存您的配置,而是在生产中,您将不会遇到像在本地发布这篇文章那样的错误。如果你有一个 ci 管道和良好的测试实践,那么这个障碍就可以克服。

如果您坚持在本地使用缓存配置,则每次更新配置文件或 .env 文件时都需要运行 php artisan config:cache

    禁用配置缓存

通过运行php artisan config:clear 或删除/bootstrap/cache/config.php,laravel 将不再尝试从缓存中读取配置,并且 .env 将在配置文件之外工作。如果您这样做,正如我在 (1) 中所述,如果您在生产环境中缓存配置,请确保您的管道中有一部分会捕获这些错误。

在与 OP 进一步讨论后,我再澄清一件事:

缓存配置不会自动缓存您的 .env 密钥,因此您可以像 config('SOME_CUSTOM_DOT_ENV_KEY') 一样访问它们。使用缓存配置时,如果需要访问应用程序内部的环境变量,则必须在配置文件中引用它们。

同样,一旦启用配置缓存,.env 将变得无用,但它用于构建缓存。

所以如果你在 .env 中说:

GOOGLE_API_TOKEN=xxxx

您可能会创建一个配置文件,例如:

google.php

return [
    'api_token' => env('GOOGLE_API_TOKEN', 'some-default-value'),
];

在您的应用程序中,您只会引用 config('google.api_token') 而不会引用 env('GOOGLE_API_TOKEN')。

【讨论】:

很好的解释

以上是关于Laravel 环境变量(没有在方法中传递默认值)在 Artisan 命令文件中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在 Laravel->Blade 中放置一些变量的最佳方法

将类变量作为默认值分配给类方法参数

如何在laravel php中将变量从视图传递到控制器而没有表单

Laravel刀片“旧输入或默认变量”?

在 Laravel 中以相同的方法将变量从一个查询传递到另一个查询

参数的传递