m1/env

Env 是一个轻量级的库,为 PHP 带来了 .env 文件解析器的兼容性。简而言之 - 它使您能够使用 PHP 读取 .env 文件。

2.2.0 2020-02-19 09:02 UTC

This package is auto-updated.

Last update: 2024-09-21 20:38:31 UTC


README

Author Latest Version on Packagist Software License Build Status Coverage Status Quality Score Downloads StyleCI

Sensio badge

Env 是一个轻量级的库,为 PHP 带来了 .env 文件解析器的兼容性。简而言之 - 它使您能够使用 PHP 读取 .env 文件。

为什么?

Env 致力于为 PHP 提供一个统一的 env 解析器,而不是让几个不完整或有错误的解析器被写入其他库。这个库不是为了像其他库那样作为一个完整的配置加载包,因为这超出了这个库的范围。如果您需要这样的东西,请查看 Vars,它包含了这个库,因此如果您想的话,可以加载 Env 和其他文件类型,或者如果您只需要 .env 解析,请查看 PHP Dotenv

需求

Env 需要 PHP 版本 5.3+ - 支持并在 5.35.45.55.67hhvm 上测试过。

安装

通过 Composer

$ composer require m1/env

使用

基本

test.env

TEST_1 = VALUE

example.php

<?php

//both examples return the same thing

// example 1 -- standard
use M1\Env\Parser;

$env = new Parser(file_get_contents('test.env'));
$arr = $env->getContent();

// example 2 -- statically
$arr = Parser::parse(file_get_contents('test.env'));

var_dump($arr);
// [
//      "TEST_1" => "VALUE"
// ]

上下文变量

test_context.env

TEST_1 = $EXTERNAL
TEST_2 = VALUE

example_context.php

<?php

//both examples return the same thing

// example 1 -- standard
use M1\Env\Parser;

$env = new Parser(file_get_contents('test_context.env'), array('EXTERNAL' => 'external'));
$arr = $env->getContent();

// example 2 -- statically
$arr = Parser::parse(file_get_contents('test_context.env'), array('EXTERNAL' => 'external'));

var_dump($arr);
// [
//      "TEST_1" => "external"
//      "TEST_2" => "VALUE"
// ]

语法

语法比 bash 略为宽松,但仍然相当类似 bash

赋值

赋值语法为 key = value,与 bash 不同,赋值相当宽松,以下任何一种都是有效的

TEST1 = value
TEST2= VALUE
TEST3 =VALUE
TEST4=VALUE
 TEST5 = VALUE
TEST6  =   VALUE

但是键不能以数字开头,例如

1notvalid = nope

将抛出 ParseException

您也可以在变量的开头添加 export 以在 bash 中 source 文件(更多信息请参见此处

export TEST1=value

字符串

字符串可以是带有引号(单引号或双引号)的,也可以不带引号

TEST1 = value
TEST2 = "value"
TEST3 = 'value'

转义换行符或引号是标准的反斜杠

TEST1 = "value \n value"
TEST2 = "value \"value\" value"
TEST3 = 'value \' value \' value'

如果您将两个带引号的字符串作为值,则只有第一个带引号的字符串将被分配给键

TEST1 = "value value" "this sentence in quotes will not be counted"

数字

数字相当标准

TEST1 = 1
TEST2 = 2

十进制数字将自动转换为浮点数

TEST1 = 1.1 # `float` type
TEST2 = 2   # `int` type

如果引用数字,则它们将被视为字符串,或者如果您在一行上有两个数字

TEST1 = 33 33 # `string` type
TEST2 = "22"  # `string` type

布尔值

布尔值可以是 truefalseyesno

TEST1 = true
TEST2 = false
TEST3 = yes
TEST4 = no

布尔值不区分大小写

TEST1 = True
TEST2 = False
TEST3 = YES
TEST4 = NO

带引号的布尔值将被视为字符串

TEST1 = "true" # `string` type
TEST2 = "YES"  # `string` type
TEST3 = 'NO'   # `string` type

空值

以下两种都被视为空值

TEST1 =
TEST2 = null

而空字符串被视为字符串

TEST1 = "" # `string` type
TEST2 = '' # `string` type

变量

变量基于 bash 语法

TEST1 = 'hello'
TEST2 = ${TEST27} # 'hello'

如果只有一个变量,则变量的类型会传递给调用变量。如果有多个变量,则调用变量会自动转换为字符串

TEST1 = 1 # `int` type
TEST2 = 2 # `int` type
TEST3 = ${TEST1} ${TEST2} # `string` type
TEST4 = true     # `bool` type
TEST5 = ${TEST4} # `bool` type

如果变量在引号内,则变量会自动转换为字符串

TEST1 = 1 # `int` type
TEST2 = "${TEST1}" # `string` type

但您可以使用不带引号的变量,并且它们将被转换为字符串

TEST1 = foo
TEST2 = bar
TEST3 = ${TEST1}/${TEST2} # `string` type

变量可以在字符串中这样使用

TEST1 = "foo"
TEST2 = 'bar'
TEST3 = "hello ${TEST1} and ${TEST2}"

如果空值在引号内传递,则会被转换为空字符串

TEST1 = null
TEST2 = ${TEST1} # `null` type
TEST3 = "${TEST1}" # `string` type

单引号中的变量将被视为字符串

TEST1 = '${hello} # `string` type, will output: '${hello}'
参数扩展

您可以进行参数展开,目前您只能进行默认值指定默认值,就像在bash语法中一样。

TEST1 = foo
TEST2 = ${TEST3:=bar}
TEST4 = ${TEST5=bar}
TEST6 = ${TEST7:-bar}
TEST8 = ${TEST9-bar}

默认值参数展开的语法是:-,关于这一点在bash-hackers wiki上的解释是:

语法

${PARAMETER:-WORD}

${PARAMETER-WORD}

如果参数PARAMETER未设置(从未定义过)或为空(空字符串),则展开为WORD,否则展开为PARAMETER的值,就像使用${PARAMETER}一样。如果您省略了:(冒号),就像第二种形式中所示,只有当参数未设置时才会使用默认值。

例如

TEST1 = foo
TEST2 = ${TEST1:-bar} # TEST1 is set so the value of TEST2 = foo

TEST3 = ${TEST4:-bar} # TEST4 is not set so the value of TEST3 = bar

TEST5 = null
TEST6 = ${TEST5-bar} # TEST5 is set but empty so the value of TEST6 = null
TEST7 = ${TEST6:-bar} # TEST5 is set and empty so the value of TEST7 = bar

指定默认值的参数展开是:=,关于这一点在bash-hackers wiki上的解释是:

语法

${PARAMETER:=WORD}

${PARAMETER=WORD}

这就像使用默认值一样工作,但您提供的默认文本不仅会被展开,而且如果参数未设置或为空,也会被分配给参数。省略:(冒号)的情况,就像第二种形式中所示,只有当参数未设置时才会分配默认值。

例如

TEST1 = foo
TEST2 = ${TEST1:=bar} # TEST1 is set so the value of TEST2 = foo

TEST3 = ${TEST4:=bar} # TEST4 is not set so the value of TEST3 = bar and TEST4 = bar

TEST5 = null
TEST6 = ${TEST5=bar} # TEST5 is set but emtpy so the value of TEST6 = null 
TEST7 = ${TEST6=bar} # TEST5 is set and empty so the value of TEST7 = bar and TEST5 = bar

注释

要注释,只需使用#语法,您也可以这样内联注释

# This is a comment
TEST1 = bar # and so is this

如果您在未引用的字符串中放置一个没有空格的#,它将被解析为字符串

TEST1 = hello#notacomment

.env 示例

# Comments are done like this

# Standard key=value
TEST1 = value
TEST2 = value
TEST3 = value # You can also comment inline like this

# Strings
TEST4 = "value"

## The value of the below variable will be TK4 = "value value"
TEST5 = "value value" "this sentence in quotes will not be counted"

## Escape newline
TEST6 = "value \n value"

## Escape double quotes
TEST7 = "value \"value\" value"

## You can also exchange any of the above for single quotes, eg:
TEST8 = 'value'
TEST9 = 'value \' value \' value'

# Numbers
TEST10 = 1
TEST11 = 1.1
TEST12 = 33 33 # Will output as a `string` -- not a number as two numbers are given
TEST13 = "33" # 33 -- `string` type

# Bools -- All of the below are valid booleans
TEST14 = true
TEST15 = false
TEST16 = yes
TEST17 = no

## Booleans are case-insensitive
TEST18 = True
TEST19 = False
TEST20 = YES
TEST21 = NO

TEST22 = "true" # "true" -- `string` type
TEST23 = "YES" # "YES" -- `string` type
TEST24 = 'NO' # "NO" -- `string` type

# Null values
TEST25 =
TEST26 = null

# Variables
TEST27 = 'hello'
TEST28 = ${TEST27} # 'hello'

TEST29 = 1
TEST30 = 2
TEST31 = ${TEST29}   # 1 -- `int` type
TEST32 = "${TEST29}" # 1 -- `string` type
TEST33 = ${TEST29} ${TEST30} # 1 2 -- `string` type

TEST34 = foo
TEST35 = bar
TEST36 = ${TEST34}/${TEST35} # foo/bar -- `string` type

TEST37 = "foo"
TEST38 = 'bar'
TEST39 = "hello ${TEST37} and ${TEST38}" # hello foo and bar -- `string` type

TEST40 = true
TEST41 = false
TEST42 = ${TEST40} # true -- `bool` type
TEST43 = ${TEST40} ${TEST41} # true false -- `string` type

TEST44 = null
TEST45 = ${TEST44} # null -- `null` type
TEST46 = "${TEST44}" # '' -- `string` type
TEST46_5 = '${TEST44}' # '' -- `string` type

TEST47=foo
TEST48=${TEST47:=bar}
TEST49=${TEST50:=foo}
TEST51=${TEST52:-foo}
TEST53=null
TEST54=${TEST53=foo}
TEST55=null
TEST56=${TEST55-foo}
TEST57=${TEST58:=""}
TEST59=${TEST60:=null} # TEST59 = null TEST60 = null -- both `null` types
TEST61=${TEST62:=true} # TEST61 = true TEST62 = true -- both `bool` types

# Comments
TEST63 = hello # comment
TEST64 = "hello # comment"
TEST65 = "hello" #comment
TEST66 = #comment
TEST67 = "#comment"
TEST68 = thisisnota#comment

该库的结果和上述期望结果相同

array(
    "TEST1" => "value",
    "TEST2" => "value",
    "TEST3" => "value",
    "TEST4" => "value",
    "TEST5" => "value value",
    "TEST6" => "value \n value",
    "TEST7" => 'value "value" value',
    "TEST8" => "value",
    "TEST9" => "value ' value ' value",
    "TEST10" => 1,
    "TEST11" => 1.1,
    "TEST12" => "33 33",
    "TEST13" => "33",
    "TEST14" => true,
    "TEST15" => false,
    "TEST16" => true,
    "TEST17" => false,
    "TEST18" => true,
    "TEST19" => false,
    "TEST20" => true,
    "TEST21" => false,
    "TEST22" => "true",
    "TEST23" => "YES",
    "TEST24" => 'NO',
    "TEST25" => null,
    "TEST26" => null,
    "TEST27" => "hello",
    "TEST28" => "hello",
    "TEST29" => 1,
    "TEST30" => 2,
    "TEST31" => 1,
    "TEST32" => "1",
    "TEST33" => "1 2",
    "TEST34" => "foo",
    "TEST35" => "bar",
    "TEST36" => "foo/bar",
    "TEST37" => "foo",
    "TEST38" => 'bar',
    "TEST39" => "hello foo and bar",
    "TEST40" => true,
    "TEST41" => false,
    "TEST42" => true,
    "TEST43" => "true false",
    "TEST44" => null,
    "TEST45" => null,
    "TEST46" => "",
    "TEST46_5" => "${TEST44}",
    'TEST47' => 'foo',
    'TEST48' => 'foo',
    'TEST50' => 'foo',
    'TEST49' => 'foo',
    'TEST51' => 'foo',
    'TEST53' => null,
    'TEST54' => null,
    'TEST55' => null,
    'TEST56' => null,
    'TEST58' => '',
    'TEST57' => '',
    'TEST60' => null,
    'TEST59' => null,
    'TEST62' => true,
    'TEST61' => true,
    'TEST63' => 'hello # comment',
    'TEST64' => 'hello',
    'TEST66' => null,
    'TEST67' => '#comment',
    'TEST68' => 'thisisnota#comment',
);

注意

源代码

如果您需要在其他应用程序中需要.env变量,可以使用source命令,但请确保它是有效的bash语法,因为这个解析器允许更宽松的bash语法形式。

source .env

这个库始终可以解析bash语法,但现在相反的情况(env语法 -> bash语法)可能不成立,然而正在努力为3.0版本提供一个严格的解析器版本。

与其他库的比较

这个库与其他类似库的区别

zrcing/phpenv:

  • 将所有值类型转换为字符串
  • 不支持null
  • 不支持intfloatbool类型
  • 不支持变量

Dotenv\Dotenv:

  • 不支持类似33 33的无引号值,这应该被转换为字符串。参见TEST12
  • 不支持类似${VAR} ${VAR2}的无引号变量的连接,这应该被转换为字符串。参见TEST33
  • 上述两种情况都会使Dotenv崩溃,而不会提供有用的异常
  • 将所有值类型转换为字符串
  • 不支持null
  • 不支持intfloatbool类型
  • 不支持变量
  • 不支持参数展开
  • 不支持没有值的内联注释。参见TEST66

待办事项

变更日志

请参阅变更日志了解最近发生了什么变化。

测试

$ composer test

贡献

请参阅贡献指南行为准则以获取详细信息。

安全

如果您发现任何与安全相关的问题,请通过电子邮件hello@milescroxford.com报告,而不是使用问题跟踪器。

致谢

许可证

MIT许可(MIT)。有关更多信息,请参阅许可文件