monolyth/envy

PHP项目(包括单元测试!)的灵活环境处理器

0.7.6 2023-02-01 14:06 UTC

This package is auto-updated.

Last update: 2024-08-29 17:35:36 UTC


README

PHP项目(包括单元测试!)的灵活环境处理器

当编写比两页网站更复杂的PHP项目时,你可能会遇到一些真实生活中的问题

  • 我是在开发环境还是生产环境?

    例如,在开发过程中,邮件发送器不应实际向用户发送邮件,而应代理给开发者。

  • 这个环境的正确数据库凭据是什么?

    理想情况下,应与生产环境相同,但遗憾的是,我们生活在一个并不理想的世界。

  • 当从命令行运行时,如何为例如 $_SERVER 值提供安全的回退?

    因为像 $_SERVER['SERVER_NAME'] 这样的值在开发环境中与生产环境不同。

  • 在测试期间,我们现在应该使用什么?

    显然,我们不想针对生产数据库进行测试。

  • 如何使用一组单元测试来测试多项目设置?

    PHPUnit和DBUnit很棒,但它们似乎都假设只有一个数据库。对于复杂项目来说,这通常并不成立。此外,多个网站可能相互关联,因此共享99%的单元测试。由于复制粘贴是邪恶的,因此最好有一种方法可以自动决定一组测试需要针对哪些数据库运行。

安装

Composer(推荐)

$ composer require monolyth/envy

手动

  1. 下载或克隆仓库;
  2. 将命名空间 Monolyth\\Envy\\ 添加到您的自动加载器中的 /path/to/envy/src

用法

从版本0.7开始,Envy仅在.env文件上工作,这似乎是行业标准。然而,我们仍然支持一些扩展。

为了构建您的环境(位于某个中央位置),实例化一个 Monolyth\Envy\Environment 类的对象。它接受两个参数:您的环境配置文件路径,以及一个哈希表,其中键是环境名称,值是布尔值或返回布尔值的调用。任何为或解析为 false 的环境都将被跳过。因此,您可以这样做

<?php

use Monolyth\Envy\Environment;

$environment = new Environment(__DIR__, [
    'prod' => $_SERVER['SERVER_NAME'] == 'example.com',
    'dev' => $_SERVER['SERVER_NAME'] == 'local.example.dev',
]);

初始实例化后,您可以使用依赖注入来访问环境,或者使用静态 Environment::instance() 方法。

您可以定义任意数量的环境,因为多个环境可以在任何时候都有效。例如,prodwebprodcli

请注意,后续定义了相同键的环境将覆盖现有键。

配置文件命名

我们使用 .env 格式,因此配置文件应命名为 .env(对于“通用”或“全局”变量,换句话说就是环境 '')或 .env.ENVIRONMENT_NAME。请注意,这些不应包含在您的VCS中!这就是 .env 文件的全部想法。唯一的例外是包含模拟值的 .env.example 文件,但为其他用户提供了一个全面的设置列表。

检查环境

您通常会想检查环境。所有定义的环境都将作为 $environment 对象上的 true 提供,否则为 false。因此,您可以这样做

<?php

if ($environment->prod) {
    if (!$environment->cli) {
        // ... logic ...
    }
} elseif ($environment->dev) {
    throw new Exception('something went wrong!');
}

使用定义的环境变量

与环境本身一样,变量作为环境对象的属性提供,或如果未定义,则为 false

通常(不知道这是否是惯例或实际要求...)环境变量是大写的。这在PHP中很丑陋。因此,所有变量都转换为小写,以方便您使用。

FOO=bar
<?php

var_dump($environment->foo); // string "bar"

自定义功能:JSON支持

对于任何可以被json_decode解码的值,将使用其实际解码的值。

自定义功能:下划线对象展开

好吧,这个名字很糟糕。这意味着对于任何包含下划线的变量名,它们实际上被视为“命名空间”,并存储在子环境中。考虑以下内容

DATABASE_NAME=foo
DATABASE_VENDOR=pgsql
DATABASE_USER=user
DATABASE_PASS=pass

这可以工作,但很麻烦。Envy会自动将其转换为

<?php

var_dump($environment->database); // object: {name: foo, vendor: pgsql, user: user, pass: pass}

这可以处理你需要的任意嵌套层级。

占位符

支持默认的.env占位符,例如

NAME=marijn
PATH=/home/${marijn}/Documents

注意事项和警告

  • 不要使用也用作变量的环境名称。变量具有优先级,因此结果可能不是你所期望的。
  • 对于“下划线展开”的对象和JSON也是类似的。根据顺序,它可能产生一种类似的工作结果,但可能不是你想要的结果。请在这里小心;要么使用JSON,要么使用展开,不要混用。

但是,以下不是问题

DATABASE_NAME=foo
DATABASE_CONFIG={"foo":"bar"}

...因为JSON解析将在下划线展开之后进行。

与其他DOTENV加载器的区别

  • Envy支持JSON和“下划线展开”以方便使用;
  • Envy支持基于条件的多个环境,例如,你可以在同一文件夹中拥有.env.dev.env.cli.env.test,并在运行时决定哪个(些)适用;
  • Envy支持->$environment检查,因此你的代码也可以根据加载的环境执行不同的操作。例如,在测试期间,你可能想加载某些模拟而不是常规依赖项,而在开发期间,你不想向实际用户发送邮件,只想发送给相关开发者以供审查。