哪个 Symfony 环境变量在哪个文件(.env、.env.local 等)中可用?

Which Symfony environment variable is available in which file (.env, .env.local, etc.)?

我刚刚开始一个新的 Symfony 5 项目(之前只在 Symfony 3 上工作过),我很难理解 .env.env.local 中的值如何协同工作。

Symfony 文档说,.env.local 中的值将覆盖 .env 中的值:

If you need to override an environment value (e.g. to a different value on your local machine), you can do that in a .env.local file:

我工作的所有机器都使用相同的基本设置(相同的数据库服务器等),但有些值不同(数据库名称、密码等)。因此,我想将通用配置放在 .env 中,将设备特定值放在 .env.local:

# .env
...
DB_SERVER="localhost"
DB_VERSION="10.4"

DB_USER=${DB_DBNAME}

DATABASE_URL="mysql://${DB_USER}:${DB_PASS}@${DB_SERVER}/${DB_DBNAME}?serverVersion=${DB_VERSION}"
# .env.local
DB_DBNAME="someDB"
DB_PASS="secretPW"

使用此设置时出现错误,php bin/console debug:container --env-vars 显示 DATABASE_URL "mysql://:@localhost/?serverVersion=10.4"。显然 DATABASE_URL 忽略了 .env.local.

中的值

我可以通过将 DATABASE_URL="mysql://... 移至 .env.local 轻松解决此问题,但这是使用 .env.env.local 的预期方式吗?

我认为这些文件的值已合并,其中 .env.local 值覆盖 .env 值。不是这样吗?还是我犯了什么错误?

我认为在这种情况下顺序是相关的:正如您在 source code 中看到的那样,.env 已完全加载,只有在 .env.local 之后才被读取。这意味着将 .env.local 中的变量设置为 .env 中的变量看起来是不可能的,而相反的方法是可行的。

documentation 也提到了这个陷阱,还有一个例子:

The order is important when some env var depends on the value of other env vars.

Which Symfony environment variable is available in which file (.env, .env.local, etc.)?

.env先于.env.local加载,每个文件相互独立处理.

为了插值目的,在 .env 文件处理期间,只有在同一文件 或在较早处理的文件 中定义的环境变量可用。

虽然在更具体的 env 文件中定义的环境变量确实胜过在更一般的文件中定义的环境变量,但在您的示例中 DB_DBNAMEDB_PASS overwritten/defined 太晚了有用,因为 DATABASE_URL(取决于那些)是较早定义的并且未在 .env.local 文件中重新定义。


但是,你可以完成你想做的事情,你只需要换一种方式。

首先,使用 参数占位符 创建您的 DATABASE_URL 环境变量,如下所示:

DATABASE_URL="mysql://%DB_USER%:%DB_PASS%@%DB_SERVER%/%DB_DBNAME%?serverVersion=%DB_VERSION%"

然后,在您的 services.yaml 文件中,为所有这些值定义容器参数:

# services.yaml
parameters:
    DB_DBNAME: "%env(DB_DBNAME)%"
    DB_USER: "%env(DB_USER)%"
    DB_PASS: "%env(DB_PASS)%"
    DB_SERVER: "%env(DB_SERVER)%"
    DB_VERSION: "%env(DB_VERSION)%"
    
# rest of your services.yaml file follows

重要的是您的学说配置应该像这样(默认设置),包括 resolve 位:

# doctrine.yaml
doctrine:
    dbal:
        url: '%env(resolve:DATABASE_URL)%'

有了这个你会得到你想要的结果。