php读取.env文件,如何使用phpdotenv完成配置读取?
发布于 作者:苏南大叔 来源:程序如此灵动~目前各种php
框架中,一般都使用.env
文件存储配置信息。在本文中,将使用vlucas/phpdotenv
来读取.env
中的配置信息。然而,这个vlucas/phpdotenv
就是读取.env
文件的最佳解决方案了么?非也,这个要看情况而定了。先定一下本文的结论:vlucas/phpdotenv
能读取市面上大部分的.env
配置文件,然而并不是全部。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码感想感悟。本文测试环境:win10
,nginx@1.15.11
,php@8.2.10-nts
。整体上来说,这个备受推崇的vlucas/phpdotenv
,基本上来说,这款“vlucas/phpdotenv
”功能不符合苏南大叔的审美。个人觉得挺难用的,【不推荐使用】。
.env文件选择
为什么说,vlucas/phpdotenv
能读取大部分的.env
文件并非全部.env
文件么?下面以常见的thinkphp
框架、laravel
框架中的.env
文件做个对比:
- https://github.com/laravel/laravel/blob/10.x/.env.example
- https://gitee.com/liu21st/thinkphp/blob/6.0/.example.env
可见:thinkphp
的部分版本,存在着部分暂时不符合标准的.env
文件,无法被标准的dotenv
程序所读取。暂做伏笔,留作后续更新。
本文中,vlucas/phpdotenv
能够读取的.env
文件,是不带分组功能的配置文件。范例如下:
# 这个是普通的配置文件,没有明显的分组功能
WWW = 苏南大叔的博客newsn.net
SERVER_ADDR = 0.0.0.0 # 这一条是故意写的,目的是测试是否能够覆盖$_SERVER变量
其实不管是哪个.env
文件格式,其实都是ini
配置文件么,换个名字就变得高大上了。
安装vlucas/phpdotenv
vlucas/phpdotenv
的github
主页地址:
vlucas/phpdotenv
存在于composer
仓库里面,所以是使用composer
安装的。
执行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__);
Immutable
和Mutable
的区别在于:是否可以覆盖已有的$_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(); # 报错
报错信息如下:
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){
//...
}
相关文章
- https://newsn.net/say/thinkphp5-debug.html
- https://newsn.net/say/composer-install-mac.html
- https://newsn.net/say/composer-install-win.html
- https://newsn.net/say/composer.html
- https://newsn.net/say/php-env-safe.html
- https://newsn.net/say/php-putenv-getenv.html
结束语
总的感觉是:vlucas/phpdotenv
提供了太多功能,但是这些功能却基本上用不到,太繁琐了不是?个人不推荐使用。
当然,大家可以去看官方文档说明,获得更多的功能说明。如果对苏南大叔的不推荐看法不同意,可以留言发表你的观点。
接下来的文章里面,将会以其它方式角度对这个.env
配置文件进行分析读取。敬请期待后续文章:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。