codemonster-ru / env
Lightweight .env loader for PHP projects
Installs: 131
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/codemonster-ru/env
Requires
- php: >=8.2
Requires (Dev)
- phpunit/phpunit: ^9.6 || ^10.5 || ^11.0 || ^12.0
Suggests
- ext-mbstring: Required for non-UTF-8 .env encodings.
README
A simple and lightweight .env loader for PHP projects.
Installation
Via Composer:
composer require codemonster-ru/env
Usage
Create a .env file in the root of your project:
APP_NAME=MyApp FEATURE_ENABLED=true FEATURE_DISABLED=false OPTIONAL_VALUE=null EMPTY_VALUE=empty SSR_URL="http://localhost:3000" WITH_SPACES="spaced value" INLINE_COMMENT=works # comment ESCAPED_HASH="foo#bar" MULTILINE="line1\nline2" export EXPORTED_VALUE=exported
Load .env in your app:
<?php require __DIR__ . '/vendor/autoload.php'; use Codemonster\Env\Env; use Codemonster\Env\EnvLoader; Env::load(__DIR__ . '/.env'); echo Env::get('APP_NAME'); // "MyApp"
Common options:
// Encoding conversion (mbstring required) Env::load(__DIR__ . '/.env', 'UTF-8'); // Size limit in bytes (negative size is invalid) Env::load(__DIR__ . '/.env', null, 1048576); Env::loadString("KEY=value\n", null, false, 1024); // Strict resolve (throws if ${VAR} or $VAR is missing) Env::load(__DIR__ . '/.env', null, null, true); // Optional file (returns false if missing/unreadable/too large) Env::safeLoad(__DIR__ . '/.env');
Parsing helpers:
Env::parse("KEY=value\n"); Env::parse("KEY=value\n", null, true); // strict, rejects duplicates Env::parseToArray("KEY=value\n"); Env::parseToArray("KEY=value\n", null, true); // strict, rejects duplicates
Multiple files and glob:
Env::loadFiles([__DIR__ . '/.env', __DIR__ . '/.env.local']); Env::loadFiles([__DIR__ . '/*.env'], null, null, false, true, GLOB_NOSORT);
ASCII-only names:
Env::setDefaultParser(new DefaultParser(true)); Env::loadString("VALID_NAME=ok\n");
Isolated loader instance:
$loader = new EnvLoader(); $loader->loadFile(__DIR__ . '/.env'); $loader->resetLoaded(); $loader->safeLoadFile(__DIR__ . '/.env'); $loader->loadFile(__DIR__ . '/.env', null, 1048576, true); $loader->loadString("KEY=value\n"); $loader->loadString("KEY=${VAR}\n", null, true); $loader->loadFiles([__DIR__ . '/.env', __DIR__ . '/.env.local']);
Notes:
- When encoding is null, no conversion is performed, even if mbstring is available.
- UTF-8 BOM is stripped automatically.
Features
- Loading
.envfiles into$_ENV,$_SERVER, and viaputenv(). - Does not override variables already present in
$_ENV,$_SERVER, orgetenv(). - Values are returned as strings; no automatic casting is applied.
- Quoted strings with escaped quotes and
\n,\r,\t,\v,\fin double quotes (single quotes are literal). - Inline comments start with
#in unquoted values (use quotes to keep a literal#). - Unquoted values cannot contain whitespace.
export KEY=valuesupport.- Unknown escape sequences in double quotes throw
InvalidFileException. - Strict parsing: invalid lines, invalid variable names, and unclosed quotes throw
InvalidFileException. ${VAR}and$VARexpansion are supported in quoted and unquoted values.${VAR}and$VARexpand in double quotes and unquoted values; single quotes keep literals.- Lines without
=are treated as empty strings. - Re-loading updates variables that were previously loaded by this library.
- Optional encoding conversion (requires
mbstring). - Optional strict resolve mode throws on unresolved
${VAR}or$VARreferences. - Default name rules allow Unicode letters/numbers; ASCII-only names are optional (via
DefaultParser(true)).
Parse Formats
| Method | Return format |
|---|---|
Env::parse() |
Raw entries: [[name, value, vars], ...] |
Env::parseToArray() |
Associative map: ['NAME' => 'value', ...] |
EnvParser::parseStringRaw() |
Raw entries: [[name, value, vars], ...] |
Strict mode throws InvalidFileException on duplicate names for parse() and parseToArray().
Load Files Order
loadFiles()processes paths in the order provided.- Glob patterns are expanded using
glob()withGLOB_BRACEby default. - Glob matches are sorted to keep load order stable.
- Use the optional
globFlagsparameter to changeglob()behavior. - If
strictResolveis true, unresolved${VAR}or$VARreferences in any loaded file will throwInvalidFileException. - If
shortCircuitis true, the first successfully loaded file stops further processing. - If
shortCircuitis false, missing files raiseInvalidPathException.
Exceptions
| Scenario | Exception |
|---|---|
| Invalid syntax, invalid name, bad escapes | Codemonster\Env\Exception\InvalidFileException |
| Invalid or unsupported encoding | Codemonster\Env\Exception\InvalidEncodingException |
| Missing or unreadable file | Codemonster\Env\Exception\InvalidPathException |
Loader Interface
You can provide your own loader by implementing Codemonster\Env\LoaderInterface:
<?php use Codemonster\Env\Env; use Codemonster\Env\LoaderInterface; class MyLoader implements LoaderInterface { public function resetLoaded(): void { // reset internal state } public function loadFile( string $path, ?string $encoding = null, ?int $maxBytes = null, bool $strictResolve = false ): void { // custom loading logic } public function safeLoadFile( string $path, ?string $encoding = null, ?int $maxBytes = null, bool $strictResolve = false ): bool { // return false if missing/unreadable return false; } } Env::setDefaultLoader(new MyLoader());
Parser Interface
You can provide a custom parser to EnvLoader by implementing Codemonster\Env\ParserInterface:
<?php use Codemonster\Env\DefaultParser; use Codemonster\Env\EnvLoader; use Codemonster\Env\ParserInterface; class MyParser implements ParserInterface { public function parseStringRaw(string $content, ?string $encoding = null): array { return (new DefaultParser())->parseStringRaw($content, $encoding); } public function expandVariables(string $value, array $vars): string { return (new DefaultParser())->expandVariables($value, $vars); } public function expandVariablesWithReport(string $value, array $vars): array { return (new DefaultParser())->expandVariablesWithReport($value, $vars); } } $loader = new EnvLoader(new MyParser());
DefaultParser accepts an optional boolean for ASCII-only variable names:
$parser = new DefaultParser(true); // match phpdotenv name rules
Testing
You can run tests with the command:
composer test