Search by

Загрузчик окружения для PHP 8.1+: dotenv-совместимый разбор с модификаторами оболочки, каскад .env/.env.local/.env.<окружение>, компиляция в PHP-кэш, типизированное чтение (числа, списки, JSON, размеры, длительности, перечисления), схема конфигурации с генерацией .env.example, маскирование секретов,

v1.2.1 2026-09-15 06:03 UTC

README

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano

CloudCastle Env

CloudCastle Env

Packagist PHP License Downloads Monthly Stars Dependents Suggesters Advisories

Quality Docs Publish Repository Issues Release Wiki Pages

PHPStan Psalm PHPMD PHPCS Coverage Infection MSI Security audit OpenSSF Scorecard

Загрузчик окружения для PHP 8.1+: совместимый с dotenv разбор с модификаторами оболочки (${VAR:-по умолчанию}, ${VAR:?сообщение}), каскад окружений (.env.env.local.env.prod), компиляция в PHP-кэш, типизированное чтение (числа, списки, JSON, размеры 512M, длительности 1h30m, перечисления), схема конфигурации с генерацией .env.example, маскирование секретов и шифрование файла окружения AES-256-GCM. Без внешних пакетов в зависимостях.

Установка

composer require cloud-castle/env

Требуется PHP 8.1+ и штатное расширение ext-openssl (шифрование хранилища).

Быстрый старт

<?php

use CloudCastle\Env\Env;
use CloudCastle\Env\Schema\Schema;
use CloudCastle\Env\Schema\VariableType;

// Каскад .env / .env.local / .env.prod с кэшем на продакшне.
Env::bootEnv('/app/.env', 'prod');

// Контракт окружения: падаем на старте, а не на первом запросе пользователя.
Env::assertSchema(Schema::fromArray([
    'APP_ENV'     => ['required' => true, 'allowed' => ['dev', 'test', 'prod']],
    'APP_KEY'     => ['required' => true, 'secret' => true, 'description' => 'Ключ подписи'],
    'DB_PORT'     => ['type' => VariableType::Integer, 'default' => '5432'],
    'UPLOAD_MAX'  => ['type' => VariableType::Bytes, 'default' => '8M'],
    'SESSION_TTL' => ['type' => VariableType::Duration, 'default' => '1h'],
]));

// Типизированное чтение — без ручного приведения строк.
$debug  = Env::getBool('APP_DEBUG', false);
$port   = Env::getInt('DB_PORT', 5432);
$upload = Env::getBytes('UPLOAD_MAX');    // 512M  → 536870912
$ttl    = Env::getSeconds('SESSION_TTL'); // 1h30m → 5400
$hosts  = Env::getList('CACHE_HOSTS');    // a,b,c → ['a', 'b', 'c']
$limits = Env::getArray('RATE_LIMITS');   // JSON  → массив

Возможности

  • Совместимый разбор .env: кавычки, экранирование, многострочные значения, комментарии, префикс export; результат совпадает с vlucas/phpdotenv, symfony/dotenv и josegonzalez/dotenv (проверяется интероп-тестами).
  • Интерполяция с модификаторами оболочки: ${VAR}, ${VAR:-умолчание}, ${VAR:+замена}, ${VAR:?сообщение}, ссылки на переменные ниже по файлу и обнаружение циклов. Подстановка команд $(…) — только с явным исполнителем.
  • Каскад окружений .env.env.local.env.<окружение> с честными приоритетами: реальные переменные процесса файлами не затираются.
  • Компиляция в PHP-кэш: продакшн не читает и не разбирает текст на каждом запросе.
  • Типизированное чтение: getInt, getFloat, getBool, getList, getArray, getBytes, getSeconds, getMap, getEnum.
  • Схема конфигурации: проверка окружения на старте, типизированные значения, генерация .env.example, поиск переменных вне контракта.
  • Хранилище под задачу: $_ENV, $_SERVER, putenv, константы, переменные Apache или изолированная память; иммутабельность и белый список изменяемых имён.
  • Безопасность: маскирование секретов в дампах, шифрование файла AES-256-GCM, права 0600 на генерируемые файлы, значения не попадают в сообщения об ошибках.
  • Инструменты: сравнение с эталоном, трассировка происхождения переменных, выгрузка в env/shell/json/php и консольная утилита cloud-castle-env.

Сравнение с аналогами

Все таблицы ниже сгенерированы автоматически из честных сравнительных прогонов (benchmarks/compare.php, benchmarks/quality.php) на одинаковых операциях и одинаковых правилах анализаторов для всех участников, без Xdebug.

_PHP 8.1.34. Участники: cloud-castle/env v1.1.3, symfony/dotenv v6.4.42, vlucas/phpdotenv v5.6.4, josegonzalez/dotenv 3.2.0, m1/env 2.2.0, phpdevcommunity/dotenv 3.0.1, parse_ini_string PHP 8.1.34._

1. Функциональность

ВозможностьCloudCastlesymfonyvlucasjosegonzalezm1phpdevcommunityparse_ini_string
Разбор пар КЛЮЧ=значение
Кавычки и экранирование
Многострочные значения в кавычках
Инлайн-комментарии
Интерполяция ${VAR} между переменными
Модификаторы ${VAR:-по умолчанию} и ${VAR:+замена}
Обязательная ссылка ${VAR:?сообщение}
Ссылки на переменные, объявленные ниже
Обнаружение циклических ссылок
Подстановка команд $(…) с явным разрешением
Загрузка из строки без обращения к диску
Каскад .env / .env.local / .env.<окружение>
Компиляция окружения в PHP-кэш
Иммутабельная загрузка (не затирает окружение)
Мутабельная перезагрузка поверх окружения
Изолированное хранилище в памяти
Выбор приёмников: $_ENV, $_SERVER, putenv
Адаптер переменных Apache
Определение констант вместо переменных
Белый список изменяемых переменных
Типизированное чтение (int/float/bool/список)
Чтение JSON-массива из переменной
Размеры с суффиксами (512M, 1.5G)
Длительности с суффиксами (1h30m, 7d)
Карты пар «ключ=значение» в одной переменной
Чтение перечислений (backed enum)
Проверка обязательных переменных и их значений
Схема конфигурации как контракт окружения
Генерация .env.example из схемы
Выявление переменных вне схемы
Сравнение файла окружения с эталоном
Трассировка происхождения переменных
Выгрузка в env / shell / json / php
Маскирование секретов в выгрузке
Шифрование файла окружения
Фильтры имён (префикс, регистр, переименование)
Разбор URL на составные переменные
Консольная утилита из коробки
Нулевые внешние пакеты в зависимостях
Всего🏆 39171312845

2. Безопасность и корректность

СвойствоCloudCastlesymfonyvlucasjosegonzalezm1phpdevcommunityparse_ini_string
Иммутабельность окружения по умолчанию
Содержимое файла не выполняет код без разрешения
Белый список изменяемых переменных
Проверка значений до старта приложения
Отказ при некорректной кодировке файла
Типизированные исключения пакета
Значения не попадают в сообщения об ошибках
Маскирование секретов в дампах
Шифрование файла окружения (AES-256-GCM)
Права 0600 на создаваемые файлы
Нулевые внешние пакеты (меньше поверхность атаки)
Всего🏆 11365322

3. Качество кода

замечания анализаторов на 1000 строк кода (меньше — лучше) и доля файлов со строгой типизацией (больше — лучше); ко всем участникам применяются одинаковые правила.

МетрикаCloudCastlesymfonyvlucasjosegonzalezm1phpdevcommunity🏆 Победитель
Ошибок синтаксиса на 1000 строк0,00,00,00,00,00,0ничья
Нарушений PSR-12 на 1000 строк0,0100,38,95,118,441,7🏆 CloudCastle
Запахов кода на 1000 строк0,041,26,510,26,84,6🏆 CloudCastle
Ошибок PHPStan (max) на 1000 строк0,0117,37,9267,983,241,7🏆 CloudCastle
Файлов с устаревшими конструкциями на 1000 строк0,07,211,413,76,832,4🏆 CloudCastle
Известных уязвимостей пакета0,00,00,00,00,00,0ничья
Файлов со строгой типизацией, %100,00,0100,00,00,00,0ничья
Сигнатур с типом возврата, %100,0100,00,00,00,057,1ничья
Побед по метрикам🏆 833222

4. Производительность: разбор файла .env

Разбор .env из 12 переменных, 100 000 раз (минимум из 4 прогонов, без Xdebug).

РешениеЗначение (мс)🏆 Победитель
parse_ini_string¹213,9базовый уровень
🏆 CloudCastle2 209,9лучший результат
m13 537,2аналог
josegonzalez4 544,5аналог
phpdevcommunity4 612,3аналог
symfony7 151,9аналог
vlucas10 638,3аналог

¹ Базовый уровень — нативные средства PHP без полноты решения; показан для контекста и не участвует в определении победителя среди библиотек.

5. Производительность: чтение переменной окружения

Загрузка файла окружения и чтение 12 значений, 10 000 раз (минимум из 4 прогонов).

РешениеЗначение (мс)🏆 Победитель
parse_ini_string¹77,2базовый уровень
🏆 CloudCastle236лучший результат
m1344,9аналог
symfony384,4аналог
josegonzalez457,3аналог
phpdevcommunity458,2аналог
vlucas1 062,3аналог

¹ Базовый уровень — нативные средства PHP без полноты решения; показан для контекста и не участвует в определении победителя среди библиотек.

6. Память: одна загрузка конфигурации

Память одной загрузки 12 переменных (изолированный процесс, только целевая библиотека).

РешениеЗначение (байт)🏆 Победитель
🏆 phpdevcommunity792лучший результат
CloudCastle1 568аналог
symfony1 568аналог
vlucas1 568аналог
parse_ini_string¹1 568базовый уровень
josegonzalez2 488аналог
m13 096аналог

¹ Базовый уровень — нативные средства PHP без полноты решения; показан для контекста и не участвует в определении победителя среди библиотек.

7. Память: десять тысяч независимых наборов (синтетический предел)

Память 10 000 удерживаемых независимых наборов переменных (изолированный процесс, содержимое уникально на каждой итерации).

РешениеЗначение (КБ)🏆 Победитель
🏆 phpdevcommunity10 828лучший результат
josegonzalez14 326аналог
CloudCastle15 829аналог
symfony15 829аналог
vlucas15 829аналог
parse_ini_string¹15 829базовый уровень
m120 329аналог

¹ Базовый уровень — нативные средства PHP без полноты решения; показан для контекста и не участвует в определении победителя среди библиотек.

8. Утечки памяти

Рост памяти за 20 циклов по 5 000 разборов (изолированный процесс, после сборки мусора).

РешениеЗначение (КБ)🏆 Победитель
🏆 CloudCastle0лучший результат
🏆 symfony0лучший результат
🏆 vlucas0лучший результат
🏆 phpdevcommunity0лучший результат
parse_ini_string¹0базовый уровень
josegonzalez120аналог
m1120аналог

¹ Базовый уровень — нативные средства PHP без полноты решения; показан для контекста и не участвует в определении победителя среди библиотек.

Коротко о плюсах и минусах

Сильные стороны:

  • Функционал — объединение возможностей аналогов. Разбор, интерполяция с модификаторами, каскад окружений, кэш, типизированное чтение, схема, фильтры, маскирование, шифрование и консоль — в одном пакете; по таблице возможностей пакет покрывает всё, что умеют пять сравниваемых аналогов вместе взятые.
  • Скорость. Быстрее всех сравниваемых библиотек и на разборе файла, и на полном цикле «загрузить и прочитать»: разбор идёт одним проходом по строке, без промежуточных объектов на каждое значение.
  • Безопасность. Содержимое файла не выполняет код (в отличие от symfony/dotenv, где подстановка команд включена всегда), иммутабельность по умолчанию, белый список изменяемых переменных, проверка кодировки, маскирование секретов, шифрование файла и права 0600 на всё, что пакет создаёт.
  • Качество кода. PHPStan max, Psalm errorLevel 1, PHPMD, PHPCS, Rector и Deptrac — без замечаний; покрытие тестами 100%, мутационный MSI 100% (все мутанты убиты).
  • Без утечек памяти. Повторные разборы не наращивают память (подтверждено сравнительным тестом утечек), состояние между вызовами не накапливается.
  • Без внешних пакетов. Только PHP 8.1+ и штатный ext-openssl: поверхность атаки и вес вендора минимальны.

Слабые стороны (честно):

  • Память на синтетическом сценарии. При удержании десяти тысяч независимых наборов пакет расходует столько же, сколько symfony/dotenv, vlucas/phpdotenv и нативный parse_ini_string, но больше, чем phpdevcommunity/dotenv и josegonzalez/dotenv: те приводят значения к скалярам (числа, пустые строки), а пакет сохраняет исходные строковые значения — иначе getString() возвращал бы не то, что написано в файле. На реальном приложении с единственной загрузкой окружения разница неощутима (1568 байт против 792 у самого экономного).
  • Возраст и распространённость. Пакет моложе vlucas/phpdotenv и symfony/dotenv, у него меньше звёзд и установок, а значит — меньше готовых рецептов в интернете и меньше сторонних интеграций.

Когда применять

  • Приложение с несколькими окружениями — основной сценарий: каскад .env, профиль окружения, проверка по схеме на старте и компиляция кэша на деплое.
  • Сервисы, где конфигурация попадает в логи и тикеты (финтех, обработка персональных данных) — маскирование секретов в дампах и исключения без значений.
  • Конфигурация рядом с кодом, но без раскрытия значений — зашифрованный .env.vault в репозитории и ключ из секрет-хранилища.
  • Строгие требования к старту — схема как контракт: приложение не поднимется с неполным или некорректным окружением, а .env.example генерируется из того же описания и не отстаёт от кода.
  • Долгоживущие процессы (RoadRunner, Swoole, воркеры очередей) — иммутабельное хранилище исключает случайную мутацию общего окружения.
  • Если нужен только разбор .env в массив и ничего больше — подойдёт и m1/env: он меньше по объёму кода, хотя и медленнее.
  • Проект на Symfony, где уже подключён symfony/dotenv — там загрузка окружения встроена в каркас; этот пакет полезен как самостоятельный слой вне фреймворка или когда нужны схема, шифрование и маскирование.

Разработка

composer install
composer check         # линтеры + статический анализ + тесты
composer fix           # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci            # полный CI-пайплайн локально
composer test:mutation # мутационное тестирование (MSI 100%)
composer docs:sync     # пересборка сравнительных таблиц, wiki и бейджей

Полный список команд с описаниями: composer run-script --list.

Документация

Лицензия

MIT © CloudCastle (alex-4-17@yandex.ru)

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano