使用之式
1.环境变量 -e APP_ENV=development 文件名字 .env.development
php start.php start -e APP_ENV=development
2.不使用环境变量, 先去找.env.development 找不到再去找.env.production 都没有就摆烂.
找一个僻静角落,轻轻放入.
<?php
namespace app\common;
class Env
{
public static function init(): void
{
global $argv;
$env = false;
$base_path = base_path() . '/.env.';
// 从环境变量获取 APP_ENV
foreach ($argv as $key => $value) {
if ($value == '-e' && isset($argv[$key + 1]) && str_contains($argv[$key + 1], '=')) {
list($name, $value) = explode('=', $argv[$key + 1]);
$envFilePath = $base_path . $value;
if ($name == 'APP_ENV' && file_exists($envFilePath)) {
$env = self::parseEnvFile($envFilePath);
if ($env) {
self::initEnv($env, $value);
return;
}
}
}
}
// 如果没有环境变量,则从 .env.development 或 .env.production 中获取
$file = 'development';
if (!file_exists($base_path . $file)) $file = 'production';
$env = self::parseEnvFile($base_path . $file);
if (!$env) {
error_log("Error: .env.development or .env.production file not found.");
exit('Error LINE:' . __LINE__);
}
self::initEnv($env, $file);
}
private static function parseEnvFile($file): false|array
{
if (!file_exists($file)) return false;
return parse_ini_file($file, true) ?? false;
}
/**
* @param array $env
* @param string $envFilePath
* @return void
*/
protected static function initEnv(array $env, string $envFilePath): void
{
self::printEnv($envFilePath);
//初始化ENV 配置
foreach ($env as $key => $val) {
//过滤首字母#或者'//'开头的注释
if (str_starts_with($key, '#') || str_starts_with($key, '//')) continue;
if (is_array($val)) {
foreach ($val as $k => $v) { //如果是二维数组 item = PHP_KEY_KEY
$item = $key . '_' . $k;
putenv("$item=$v");
}
} else {
putenv("$key=$val");
}
}
}
/**
* 多进程下只输出一次 env 名字
* @param string $envFilePath .env 名字
* @return void
*/
private static function printEnv(string $envFilePath): void
{
$lockFilePath = runtime_path() . '/env_printed.lock';
$timeout = 3;
$lockFile = fopen($lockFilePath, 'a+');
if ($lockFile === false) {
error_log("Could not open lock file: " . $lockFilePath);
return;
}
if (!flock($lockFile, LOCK_EX)) {
error_log("Could not acquire lock on file: " . $lockFilePath);
fclose($lockFile);
return;
}
try {
if (file_exists($lockFilePath)) {
$modifiedTime = filemtime($lockFilePath);
if (time() - $modifiedTime > $timeout) {
// 锁失效,输出语句并更新时间
echo "Load env file: " . $envFilePath . PHP_EOL;
touch($lockFilePath); // 更新修改时间为当前时间
}
// 如果锁未失效,不输出
} else {
// 文件不存在,输出语句并创建文件
echo "Load env file: " . $envFilePath . PHP_EOL;
touch($lockFilePath); // 创建文件并设置修改时间为当前时间
}
} finally {
flock($lockFile, LOCK_UN);
fclose($lockFile);
}
}
}
掰开 config/server.php
在return 之前加入一行
\app\common\Env::init();
return [....];
使用 getenv获取环境变量
或者封装一个助手函数
function envs($key, $default = null): string|array|null
{
$value = getenv($key, true);
if ($value === false) return $default;
return $value;
}
第二部分,//从.env 文件获取 WENMAN_ENV=development env文件全名 .env.development
.env.development没有判断是否存在文件,如果在.env里配置了WENMAN_ENV但是却没有这个文件,会报错。修正如下:
对,我已经改了好多版了这里忘记改了
很棒,建议官方添加支持变成feature
啥需求,没看懂