Jardis Core DotEnv is a PHP library for reading .env* files with advanced features like type casting, variable substitution, and environment-specific file loading.
The extracted values can be made available either globally ($_ENV, $_SERVER, putenv()) or in protected contexts, such as domain-specific configurations. This approach enables different environment settings for different application domains without interference—particularly useful when refactoring monolithic applications into domain-driven architectures.
- Global and protected contexts: Load values into
$_ENV/$_SERVERor return as isolated arrays - Automatic type casting: Converts strings to
bool,int,float, orarraybased on content - Variable substitution: Use
${VARIABLE_NAME}syntax for dynamic value resolution - Home directory expansion: Automatically expands
~to the user's home path - Environment-specific loading: Automatically loads
.env,.env.local,.env.{APP_ENV}, and.env.{APP_ENV}.localfiles - Array support: Parse both indexed and associative arrays with nested type casting
- Fully customizable: Inject custom file readers, type casters, or file discovery strategies
- PSR-4 Compatible: Follows PSR-4 autoloading standards
composer require jardiscore/dotenv- PHP >= 8.2
- jardispsr/dotenv ^1.0
use JardisCore\DotEnv\DotEnv;
$dotEnv = new DotEnv();
// Load .env files into global scope ($_ENV, $_SERVER, putenv)
$dotEnv->loadPublic('/path/to/app');
// Load .env files into protected scope (returns array without polluting globals)
$domainEnv = $dotEnv->loadPrivate('/path/to/domain');The library automatically casts values to the following types:
| Type | Example |
|---|---|
| String | APP_NAME=MyApp |
| Boolean | DEBUG=true or DEBUG=false |
| Integer | MAX_CONNECTIONS=100 |
| Float | TIMEOUT=2.5 |
| Array | PORTS=[80,443] or CONFIG=[key=>value,nested=>[1,2,3]] |
# Strings
APP_NAME=MyApplication
# Booleans
DEBUG=true
MAINTENANCE=false
# Numerics
MAX_CONNECTIONS=100
TIMEOUT=2.5
# Arrays (indexed and associative with nested type casting)
PORTS=[80,443,8080]
CONFIG=[host=>localhost,port=>3306,options=>[ssl=>true,timeout=>30]]
# Variable substitution
DB_HOST=localhost
DB_NAME=mydb
DATABASE_URL=mysql://${DB_HOST}/${DB_NAME}
# Home directory expansion
LOG_PATH=~/logs/app.logThe library automatically loads files in the following order based on the APP_ENV environment variable:
.env- Base configuration.env.local- Local overrides (not committed to version control).env.{APP_ENV}- Environment-specific (e.g.,.env.production,.env.development).env.{APP_ENV}.local- Local environment-specific overrides
Example:
# Set environment
export APP_ENV=production
# Will load (if they exist):
# 1. .env
# 2. .env.local
# 3. .env.production
# 4. .env.production.localAdd or remove type casting classes to customize value transformation:
use JardisCore\DotEnv\Casting\CastTypeHandler;
use JardisCore\DotEnv\Casting\CastStringToBool;
$castTypeHandler = new CastTypeHandler();
// Add custom type caster
$castTypeHandler->setCastTypeClass(MyCustomCaster::class);
// Remove existing type caster
$castTypeHandler->removeCastTypeClass(CastStringToBool::class);Type Casting Chain:
The CastTypeHandler runs the following casters in sequence (stops early if value becomes non-string):
CastStringToValue- Variable substitution (${VAR})CastUserHome- Home directory expansion (~)CastStringToNumeric- Numeric conversionCastStringToBool- Boolean conversionCastStringToArray- Array parsing
Customize the entire processing pipeline via constructor injection:
use JardisCore\DotEnv\DotEnv;
use JardisCore\DotEnv\Reader\LoadFilesFromPath;
use JardisCore\DotEnv\Reader\LoadValuesFromFiles;
use JardisCore\DotEnv\Casting\CastTypeHandler;
$dotEnv = new DotEnv(
fileFinder: new LoadFilesFromPath(), // Custom file discovery
fileContentReader: new LoadValuesFromFiles( // Custom file parsing
new CastTypeHandler()
),
CastTypeHandler: new CastTypeHandler() // Custom type casting
);Customization Points:
LoadFilesFromPath: Change which files are loaded and in what orderLoadValuesFromFiles: Modify how file contents are parsed (e.g., different comment syntax)CastTypeHandler: Add/remove type converters or change their execution order
-
DotEnv(src/DotEnv.php) Main entry point with two public methods:loadPublic(string $path): Loads.envfiles and populates$_ENV,$_SERVER, andputenv()loadPrivate(string $path): Loads.envfiles and returns values as an array without polluting global state
-
File Readers (
src/reader/)LoadFilesFromPath: Determines which.envfiles to load based on directory path andAPP_ENVvariableLoadValuesFromFiles: Reads.envfiles line by line, ignores comments (#), delegates type casting
-
Type Casters (
src/casting/)CastTypeHandler: Orchestrates type conversion chainCastStringToValue: Variable substitution (${VAR_NAME})CastUserHome: Expands~to user home directoryCastStringToNumeric: Converts numeric strings toint/floatCastStringToBool: Converts"true"/"false"to booleanCastStringToArray: Parses array syntax[1,2,3,key=>value]
# Install dependencies
make install
# Run all quality checks
make phpcs phpstan phpunitAll development commands use Docker Compose. Run make help for the complete list.
Dependency Management:
make install # Install composer dependencies
make update # Update composer dependencies
make autoload # Regenerate autoloaderTesting:
make phpunit # Run all tests
make phpunit-coverage # Run tests with text coverage
make phpunit-coverage-html # Generate HTML coverage report
make phpunit-reports # Generate clover/XML coverage reportsCode Quality:
make phpstan # Run static analysis (level 8)
make phpcs # Run coding standards check (PSR-12)Docker:
make shell # Open shell in PHP container
make remove # Remove all containers, images, volumes# Run a specific test file
docker compose -f support/docker-compose.yml run --rm phpcli \
vendor/bin/phpunit --bootstrap ./tests/bootstrap.php tests/unit/DotEnvTest.php
# Run tests for a specific directory
docker compose -f support/docker-compose.yml run --rm phpcli \
vendor/bin/phpunit --bootstrap ./tests/bootstrap.php tests/unit/casting/This project enforces strict quality standards:
- PHPStan: Level 8 static analysis
- PHPCS: PSR-12 coding standard (120 char soft limit, 150 hard limit)
- PHPUnit: Comprehensive test coverage
- Pre-commit hooks: Automated validation before commits
Git hooks are automatically installed via composer post-install-cmd. The hook validates:
- Branch naming:
feature/,fix/, orhotfix/followed by{issue_number}_{description}Example:feature/123_add-type-casting - Git username must not contain special characters
- All staged PHP files must pass PHPCS standards
- All classes use
declare(strict_types=1)and strict type hints - Reader classes are invokable (
__invoke()method) - Caster classes accept
CastTypeHandlerin constructor for recursive casting - Public methods throw
Exception(no custom exception hierarchy) - Array type hints use PHPDoc:
@param array<string, mixed>
MIT License - see LICENSE file for details