PHPdotenv文件解析

4.0.0 2023-05-29 22:49 UTC

README

Build Status Coverage Status Total Downloads Latest Stable Version

PHP Dotenv

PHP的.env文件解析和加载库。

要求

  • PHP 5.5+

安装

[使用 Composer]

运行 composer require josegonzalez/dotenv:

或者将插件添加到项目的composer.json文件中 - 例如这样

  {
    "require": {
      "josegonzalez/dotenv": "3.3.0"
    }
  }

使用方法

创建新的加载器

<?php
$Loader = new josegonzalez\Dotenv\Loader('path/to/.env');
// Parse the .env file
$Loader->parse();
// Send the parsed .env file to the $_ENV variable
$Loader->toEnv();
?>

大多数方法直接返回加载器,所以以下也是可能的

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->toEnv(); // Throws LogicException if ->parse() is not called first
?>

您可以使用具有以下功能的任何一种.env文件

# comments are allowed
FOO=bar # you can also have comments on the end of a line
export BAR=baz # you can optionally begin with an `export` statement

# both single and double quotes are allowed
BAZ='qux'
QUX="quux"

# as are escaped quotes or similar:
QUUX="corge \" grault"
CORGE='garply" waldo'

# unquoted values containing [null, true, false] are turned into
# their PHP equivalents
PHP_NULL=null
PHP_TRUE=true
PHP_FALSE=false

# when quoted, they are simply string values
STRING_NULL="null"
STRING_TRUE="true"
STRING_FALSE="false"

# spaces are allowed as well
# in a slightly more relaxed form from bash
 GRAULT =fred
GARPLY = plugh
SPACES=" quote values with spaces" # will contain preceding space

# When using newlines, you should use quoted values
QUOTED_NEWLINE="newline\\nchar"

# you can even have nested variables using `${VAR}` syntax
# remember to define the nested var *before* using it
WALDO=${xyzzy} # not yet defined, so will result in WALDO = `{}`
THUD=${GARPLY} # will be defined as `plugh`

# note that variables beginning with a character
# other than [a-zA-Z_] shall throw a ParseException
01SKIPPED=skipped

# However, numbers *are* allowed elsewhere in the key
NOT_SKIPPED1=not skipped # will have the value `not`

示例.env文件可在fixtures目录中找到。

定义常量

您还可以从env文件自动定义常量

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->define(); // Throws LogicException if ->parse() is not called first
?>

已定义的常量将导致立即抛出LogicException

添加到$_ENV

<?php
$overwriteENV = true;
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->toEnv($overwriteENV); // Throws LogicException if ->parse() is not called first
?>

已定义的$_ENV条目将导致立即抛出LogicException,除非$overwriteENV设置为true(默认false)。

添加到$_SERVER

<?php
$overwriteSERVER = true;
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->toServer($overwriteSERVER); // Throws LogicException if ->parse() is not called first
?>

已定义的$_SERVER条目将导致立即抛出LogicException,除非$overwriteSERVER设置为true(默认false)。

apache_getenv()可用

当使用带有mod_php的Apache Web服务器时,应优先使用此方法。

<?php
$overwrite = true;
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->apacheSetenv($overwriteAPACHE); // Throws LogicException if ->parse() is not called first
                                                // May throw a PHP Error if either apache_setenv() or apache_putenv() are not available
?>

已定义的apache_getenv()条目将导致立即抛出LogicException,除非$overwriteAPACHE设置为true(默认false)。

getenv()可用

<?php
$overwrite = true;
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->putenv($overwriteENV); // Throws LogicException if ->parse() is not called first
?>

已定义的getenv()条目将导致立即抛出LogicException,除非$overwriteENV设置为true(默认false)。

设置键前缀

<?php
$environment = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->prefix('FOO')
              ->toServer(); // BAR=baz becomes FOOBAR=baz
?>

作为数组返回

<?php
$environment = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->toArray(); // Throws LogicException if ->parse() is not called first
?>

作为JSON返回

<?php
$jsonEnvironment = (string)((new josegonzalez\Dotenv\Loader('path/to/.env'))->parse());
?>

需要环境变量

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->expect('FOO', 'BAR', 'BAZ'); // Throws RuntimeException if variables are missing
?>

关闭异常

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->raiseExceptions(false)
              ->parse()
              ->expect('FOO', 'BAR', 'BAZ'); // Returns false if variables are missing
?>

跳过现有环境变量

在容器化/Docker设置中,可以跳过现有的环境变量。

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->skipExisting() //Skip any environment variables that are already present
              ->putenv();
?>

过滤环境

可以通过使用过滤类来可选地过滤php-dotenv生成环境数据。一个过滤类有一个像这样的__invoke方法

<?php
class LollipopFilter
{
    /**
     * Sets every key's value to the string `lollipop`
     *
     * @param array $environment Array of environment data
     * @param array $config Array of configuration data that includes the callable
     * @return array
     */
    public function __invoke(array $environment, array $config)
    {
        $newEnvironment = [];
        foreach ($environment as $key => $value) {
            $newEnvironment[$key] = 'lollipop';
        }
        return $newEnvironment;
    }
}
?>

您可以使用setFilters()方法附加过滤器,这将覆盖所有当前指定的过滤器。如果指定了无效的过滤器,则将抛出LogicException

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->setFilters(['LollipopFilter']); // Takes an array of namespaced class names
?>

请注意,您可以可选地为过滤器设置配置。这些作为第二个参数传递给__invoke方法。

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->setFilters([
                'LollipopFilter' => ['paintshop'],
              ]); // Takes an array of namespaced class names
?>

过滤器也可以是可调用的函数,这在一次性情况下非常有用。它们由特殊的CallableFilter包装。

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->setFilters([function ($data) {
                return $data;
              }]);
?>

如果您需要对可调用的过滤器进行特殊配置,您可以在可调用前缀上加上__callable__N,其中N是可调用的数组中的整数索引。可调用本身应包含在callable配置键中,如下所示

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->setFilters([
                '__callable__0' => [
                  'callable' => function ($data, $config) {
                    return $data;
                  },
                  'someKey' => 'value',
                ]
              ]);
?>

最后,在调用parse()之后,必须调用filter()来调用过滤器。

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->setFilters(['LollipopFilter'])
              ->parse()
              ->filter();
?>

可用过滤器

以下过滤器是php-dotenv内置的。

  • josegonzalez\Dotenv\Filter\CallableFilter:包装一个可调用对象,并在环境变量中调用它。
  • josegonzalez\Dotenv\Filter\LowercaseKeyFilter:将环境变量的所有键转换为小写,以达到单层深度。
  • josegonzalez\Dotenv\Filter\NullFilter:返回未做任何更改的环境变量数据。
  • josegonzalez\Dotenv\Filter\RemapKeysFilter:将特定的键在 $config 数组中重新映射到单一深度的值集。
  • josegonzalez\Dotenv\Filter\UnderscoreArrayFilter:将平面数组扩展为嵌套数组。例如,['0_Foo_Bar' => 'Far'] 变为 [['Foo' => ['Bar' => 'Far']]]
  • josegonzalez\Dotenv\Filter\UppercaseFirstKeyFilter:将环境变量的所有键的第一个字母转换为大写,以达到单层深度。
  • josegonzalez\Dotenv\Filter\UrlParseFilter:当存在带有后缀 _URL 的键时,此过滤器使用 parse_url 向环境变量添加额外数据。

静态环境定义

您也可以通过静态 load 方法调用它,该方法接受一个参数数组。如果指定了方法名,则该方法使用 $options 数组中的值作为参数调用。

<?php
josegonzalez\Dotenv\Loader::load(array(
  'filepath' => 'path/to/.env',
  'expect' => array('FOO', 'BAR', 'BAZ'),
  'toEnv' => true,
  'toServer' => true,
  'define' => true,
));
?>

验证外部环境

在某些情况下,可能需要验证给定的环境变量数据数组是否符合您的需求。您可以通过独立 Expect 类使用 Loader->expect() 功能。

<?php
use josegonzalez\Dotenv\Expect;

$expect = new Expect($env);
$expect('FOO'); // Raises a RuntimeException if `env` is missing FOO

// You can turn off exception raising using the second `raise` argument
$expect = new Expect($env, false);
$expect('FOO'); // Returns false if `env` is missing FOO
?>

这是什么?为什么我应该使用它?

在开发和部署应用程序时,您通常会与各种环境进行交互 - 例如生产环境和开发环境。这两个环境都会执行您的代码,但它们将使用不同的凭证。您还可能希望将应用程序分发给开发人员,而不会无意中让他们访问重要外部服务。

简单的例子包括电子邮件提供商的认证密钥或数据库连接凭证。您绝对不希望不小心向所有用户发送测试邮件,或者在运行单元测试时运行 DROP TABLE 语句。

如何处理这些不同的凭证?php-dotenv 通过允许您以通用方式配置环境,使其易于安全地在环境之间切换,以及与多个项目/语言共享这些环境来解决此问题。

还需要更多理由吗?请查看 十二因素应用程序配置文档

遵循的规则

当使用 php-dotenv 时,您应该努力遵循以下规则

  • 将您的 .env 文件添加到 gitignore 中,并使用 .env.default.env.example 为您的项目设置默认值。这允许您的开发团队以适合他们本地环境的方法覆盖默认值。

  • 始终为任何凭证设置合理的开发默认值。如果需要,当凭证“无效”时禁用功能。

  • 在必要时,对凭证添加注释,说明它们是什么,如何使用它们,以及如何获取新的凭证。

  • 由于 php-dotenv 在定义环境变量时使用更宽松的程序,请确保您的 .env 文件与您的 shell 兼容。一个很好的测试方法是运行以下命令

    # source in your .env file
    source .env
    # check the environment
    env
  • 避免在生产设置中运行 php-dotenv,而是在运行命令之前,在您的 web 服务器、进程管理器中或在 bash 中设置环境变量。一个简单的方法是检查是否存在一个仅在生产中设置的哨兵环境变量

    // APP_NAME isn't set in staging/dev
    if (!env('APP_NAME')) {
        $loader = new josegonzalez\Dotenv\Loader([
            __DIR__ '/.env',
            __DIR__ '/.env.default'
        ]);
        $loader->parse()->toEnv();
    }

一般安全信息

如果您配置 php-dotenv 以任何上述方式输出配置并导出,它们可能对不需要的用户可用。例如,使用类似 filp/whoops 的项目与 $Loader->toServer() 结合使用,如果在生产环境中启用 whoops,则可能导致向用户输出敏感数据。

因此,php-dotenv 默认不会将数据填充到环境变量中,并要求开发者做出有意识的决策,关于他们想要如何使用加载的环境变量。

许多错误报告工具提供了将敏感数据加入白名单或黑名单的选项,您应该熟悉这些工具。

许可证

MIT许可证(MIT)

版权所有(c)2013 Jose Diaz-Gonzalez

在此特此免费许可任何人,无需支付费用即可获取本软件及其相关文档文件(以下简称“软件”)的副本,以无限制地处理软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许将软件提供给他人以进行上述操作,前提是遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

软件按“现状”提供,不提供任何形式的保证,无论是明示的、暗示的,还是针对适销性、特定目的适用性或非侵权性的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论是基于合同、侵权或其他法律行为,也不论是由于软件或其使用或其他与软件相关的行为引起的。