
本文介绍一种健壮、兼容性强的 php 方法,用于读取无节标题的 `.env` 文件(如 `key=value` 形式),准确提取键值对并忽略注释与空行,特别处理含多个等号(如 base64 密钥)的特殊情况。
.env 文件虽常被误认为是标准 INI 文件,但其实际格式并不符合 parse_ini_file() 的语法要求——该函数强制依赖节(section)定义(如 [section]),且对值中出现的多个 = 号(如 APP_KEY=base64:xxx=yyy=zzz)会解析失败,导致返回 false。直接 include() 更不可取,因其将文件当作 PHP 代码执行,存在严重安全风险(如任意代码注入)且无法返回结构化数据。
因此,推荐采用手动逐行解析策略,兼顾安全性、鲁棒性与可维护性。核心逻辑如下:
- 使用 file() 读取文件为行数组,并自动跳过空行与保留换行符;
- 对每行去除首尾空白,跳过以 # 或 ; 开头的注释行;
- 精确识别第一个 = 位置,将左侧作为键(key),右侧全部作为值(value),从而兼容密钥、URL、JSON 片段等含多等号的合法值;
- 自动过滤空键,避免无效条目。
以下是生产就绪的完整实现:
function loadEnvFile(string $filepath): array
{
if (!is_file($filepath) || !is_readable($filepath)) {
throw new InvalidArgumentException("Cannot read .env file: {$filepath}");
}
$data = [];
$lines = file($filepath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
$line = trim($line);
// 跳过空行和注释行(支持 # 和 ; 开头)
if (empty($line) || str_starts_with($line, '#') || str_starts_with($line, ';')) {
continue;
}
// 查找第一个等号位置,确保值中可含多个 =
$pos = strpos($line, '=');
if ($pos === false) {
continue; // 跳过无等号的异常行
}
$key = trim(substr($line, 0, $pos));
$value = trim(substr($line, $pos + 1));
// 可选:移除值两端的引号(兼容带单/双引号的 .env 写法)
if (strlen($value) >= 2 && ($value[0] === '"' && $value[-1] === '"') ||
($value[0] === "'" && $value[-1] === "'")) {
$value = substr($value, 1, -1);
}
if ($key !== '') {
$data[$key] = $value;
}
}
return $data;
}
// 使用示例
try {
$env = loadEnvFile(__DIR__ . '/../../.env');
print_r($env);
} catch (InvalidArgumentException $e) {
error_log('Failed to load .env: ' . $e->getMessage());
}✅ 优势说明:
立即学习“PHP免费学习笔记(深入)”;
- 安全:不执行任何外部代码,杜绝 include() 类风险;
- 兼容:正确处理 APP_KEY=base64:...=、APP_URL=https://example.com/path?x=y&z=w 等复杂值;
- 健壮:跳过注释、空行、无等号行,避免崩溃;
- 可扩展:已内置引号剥离逻辑,适配 Laravel / Symfony 等主流框架的 .env 写法。
⚠️ 注意事项:
- 切勿将 .env 文件置于 Web 可访问目录(如 public/),防止敏感信息泄露;
- 生产环境建议使用环境变量替代文件读取(如通过 putenv() + getenv()),更高效且安全;
- 如需深度集成(如变量插值、多环境继承),建议使用成熟库如 vlucas/phpdotenv,本方案适用于轻量、无依赖场景。
通过以上方法,你即可稳定、清晰地将 .env 配置加载为 PHP 关联数组,为后续应用初始化、数据库连接或 API 配置提供可靠数据源。











