我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

目前各种php框架中,一般都使用.env文件存储配置信息。在本文中,将使用vlucas/phpdotenv来读取.env中的配置信息。然而,这个vlucas/phpdotenv就是读取.env文件的最佳解决方案了么?非也,这个要看情况而定了。先定一下本文的结论:vlucas/phpdotenv能读取市面上大部分的.env配置文件,然而并不是全部。

苏南大叔:php读取.env文件,如何使用phpdotenv完成配置读取? - phpdotenv读取配置
php读取.env文件,如何使用phpdotenv完成配置读取?(图4-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码感想感悟。本文测试环境:win10nginx@1.15.11php@8.2.10-nts。整体上来说,这个备受推崇的vlucas/phpdotenv,基本上来说,这款“vlucas/phpdotenv”功能不符合苏南大叔的审美。个人觉得挺难用的,【不推荐使用】。

.env文件选择

为什么说,vlucas/phpdotenv能读取大部分的.env文件并非全部.env文件么?下面以常见的thinkphp框架、laravel框架中的.env文件做个对比:

可见:thinkphp的部分版本,存在着部分暂时不符合标准的.env文件,无法被标准的dotenv程序所读取。暂做伏笔,留作后续更新。

苏南大叔:php读取.env文件,如何使用phpdotenv完成配置读取? - 格式区别
php读取.env文件,如何使用phpdotenv完成配置读取?(图4-2)

本文中,vlucas/phpdotenv能够读取的.env文件,是不带分组功能的配置文件。范例如下:

# 这个是普通的配置文件,没有明显的分组功能
WWW = 苏南大叔的博客newsn.net
SERVER_ADDR = 0.0.0.0  # 这一条是故意写的,目的是测试是否能够覆盖$_SERVER变量
其实不管是哪个.env文件格式,其实都是ini配置文件么,换个名字就变得高大上了。

安装vlucas/phpdotenv

vlucas/phpdotenvgithub主页地址:

vlucas/phpdotenv存在于composer仓库里面,所以是使用composer安装的。

苏南大叔:php读取.env文件,如何使用phpdotenv完成配置读取? - github-phpdotenv
php读取.env文件,如何使用phpdotenv完成配置读取?(图4-3)

执行composer命令:

composer require vlucas/phpdotenv

然后就会在根目录下面生成vendor目录了,目录下的autoload.php文件是需要被引入的。

require "./vendor/autoload.php";

Immutable 和 Mutable

默认加载同级目录下的.env文件:

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv = Dotenv\Dotenv::createMutable(__DIR__);

ImmutableMutable的区别在于:是否可以覆盖已有的$_ENV/$_SERVER变量条目。

灵魂发问:为啥非要跟系统变量过不去?为啥非要覆盖系统变量...自己单独出来,它不香么?

  • 说实话,覆盖或者不覆盖$_ENV,个人完全无感。毕竟这个变量很少使用。
  • 但是$_SERVER变量还是经常使用的,个人可不希望$_SERVER变量里面的某个条目被覆盖掉。
  • 如果非要选择一个的话,个人觉得应该选择不覆盖,也就是“createImmutable()”。
静态方法名翻译$_ENV/$_SERVER已有条目$_ENV/$_SERVER不存在的条目
Immutable恒定不变的已有条目【不】覆盖没有的条目会新增
Mutable可变的已有条目【会】覆盖没有的条目会新增

测试代码:

require "./vendor/autoload.php";

var_dump($_ENV);  // env是空的,server当然不是空,只需关心“SERVER_ADDR”是否被覆盖即可...

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
echo "createImmutable():\r\n\r\n";

// $dotenv = Dotenv\Dotenv::createMutable(__DIR__);
// echo "createMutable():\r\n\r\n";

$dotenv->safeload();

echo "\$_SERVER:\r\n";
var_dump(@$_SERVER["SERVER_ADDR"]);  // 是否被覆盖呢?
var_dump(@$_SERVER["WWW"]);          // 必须新增


echo "\r\n\$_ENV:\r\n";
var_dump(@$_ENV["SERVER_ADDR"]);    // 虽然env里没有,但是server里面有...
var_dump(@$_ENV["WWW"]);            // 必须新增


echo "\r\ngetenv():\r\n";
var_dump(getenv("SERVER_ADDR"));    // 不新增可能覆盖,却读取到了server中的值...
var_dump(getenv("WWW"));            // 然而拿不到数据...

【输出Immutable】:

array(0) {
}
createImmutable():

$_SERVER:
string(9) "127.0.0.1"
string(30) "苏南大叔的博客newsn.net"

$_ENV:
NULL
string(30) "苏南大叔的博客newsn.net"

getenv():
string(9) "127.0.0.1"
bool(false)

【输出Mutable】:

array(0) {
}
createMutable():

$_SERVER:
string(9) "127.0.0.1"
string(30) "苏南大叔的博客newsn.net"

$_ENV:
NULL
string(30) "苏南大叔的博客newsn.net"

getenv():
string(9) "127.0.0.1"
bool(false)

参考文章:

自定义配置文件名

可以使用默认的.env文件,也可以使用自己喜欢的新文件名。比如.env2

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__, '.env2');
$dotenv = Dotenv\Dotenv::createMutable(__DIR__, '.env2');

load() 和 safe_load()

获得了$dotenv变量后,就可以使用load()方法了。根据对待配置文件不存在的时候,如何处理的问题,有两个分支:

$dotenv->load();
$dotenv->safeLoad();

两者的区别如下:

方法目标配置文件不存在的时候
->safeLoad()不报错
->load()直接报错

测试代码:

require "./vendor/autoload.php";

$dotenv = Dotenv\Dotenv::createMutable(__DIR__,"404.env");
$dotenv->safeload();      # 不报错
echo "配置文件不存在,safeload 不报错\r\n";
echo "配置文件不存在,load 报错\r\n";
$dotenv->load();          # 报错

苏南大叔:php读取.env文件,如何使用phpdotenv完成配置读取? - 报错不报错
php读取.env文件,如何使用phpdotenv完成配置读取?(图4-4)

报错信息如下:

Fatal error: Uncaught Dotenv\Exception\InvalidPathException: Unable to read any of the environment file(s) 

读取配置条目

可以使用下面的语句读取到配置条目:

$_name = $_SERVER['WWW'];
$_name = $_ENV['WWW'];
$_name = getenv('WWW');

苏南大叔经过尝试,感觉vlucas/phpdotenv提供的这三种方式,都不是很靠谱。所以,还是强烈不推荐使用。理由如下:

  • $_SERVER的方式,如果选择的是Immutable,而恰好是个内置的名字的话,则读取不到目标数据。【非要选一个的话,只能选这个了...】
  • $_ENV的方式,如果选择的是Immutable,而恰好是个内置的名字的话(即使内置在$_SERVER里面),拿不到目标数据。返回Null
  • getenv()的方式,拿得到$_SERVER$_ENV原有的内容,却拿不到新增的内容,返回false

合理性验证

vlucas/phpdotenv提供了一些项目验证方式,感觉用到的概率不是很大。
所以具体的看文档吧,或者看代码自己猜意思,很好猜的。

示例代码:

$dotenv->required('DATABASE_DSN');
$dotenv->required(['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASS']);
$dotenv->required('DATABASE_DSN')->notEmpty();
$dotenv->required('FOO')->isInteger();
$dotenv->ifPresent('FOO')->isInteger();
$dotenv->required('FOO')->isBoolean();
$dotenv->ifPresent('FOO')->isBoolean();
$dotenv->required('SESSION_STORE')->allowedValues(['Filesystem', 'Memcached']);
$dotenv->required('FOO')->allowedRegexValues('([[:lower:]]{3})');

这里需要注意的是:验证不通过的时候,会抛出错误信息。

文件解析错误

目前有两种情况,可能会抛出错误:

  • 配置文件不存在。
  • 内容无法解析(比如使用了thinkphp部分版本的.env文件)。
  • 配置项目无法通过验证。

那么,可以通过下面的类似代码捕获错误信息:

try{
    //...
}
catch (Exception $exception){
    //...
}

相关文章

结束语

总的感觉是:vlucas/phpdotenv提供了太多功能,但是这些功能却基本上用不到,太繁琐了不是?个人不推荐使用。

当然,大家可以去看官方文档说明,获得更多的功能说明。如果对苏南大叔的不推荐看法不同意,可以留言发表你的观点。

接下来的文章里面,将会以其它方式角度对这个.env配置文件进行分析读取。敬请期待后续文章:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   php