A lightweight configuration and environment-loading library for PHP applications.
AmunCode Config provides a small set of focused classes for loading environment variables from a .env file, reading environment values, loading PHP configuration files, and accessing configuration values with dot notation.
- PHP
>= 8.4.1 - Symfony Finder
^8.1 - PHP dotenv
^5.8
Install the package with Composer:
composer require amuncode/configComposer installs the required dependencies and configures the AmunCode\Config\ namespace through PSR-4 autoloading.
- Load
.envfiles optionally or require them to exist. - Load environment variables without overwriting variables that are already present.
- Read environment values from
$_ENV,$_SERVER, andgetenv(). - Normalize Laravel-style values such as
true,false,null, andempty. - Load top-level PHP configuration files from a directory.
- Retrieve and update configuration values using dot notation.
- Recursively merge configuration arrays.
Load the environment before loading PHP configuration files. This allows configuration files to read environment values safely.
The following example assumes the script is located in the project's public/ directory:
<?php
declare(strict_types=1);
use AmunCode\Config\Config;
use AmunCode\Config\EnvironmentLoader;
$root = dirname(__DIR__);
// Load .env if it exists.
$environment = new EnvironmentLoader();
$environment->load($root);
// Load PHP configuration files from the config directory.
$config = new Config($root . '/config');
$appName = $config->get('app.name', 'My Application');
$debug = $config->get('app.debug', false);EnvironmentLoader and Config have separate responsibilities. EnvironmentLoader loads environment variables; Config loads PHP configuration files. The Config constructor does not load .env files.
AmunCode Config uses PHP dotenv to load environment variables from a .env file.
Create a .env file in your project root:
APP_NAME="My Application"
APP_DEBUG=true
APP_ENV=development
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_database
DB_USERNAME=root
DB_PASSWORD=For other developers, provide an .env.example file with placeholder values. Do not commit your actual .env file or real credentials.
Use EnvironmentLoader to load the environment variables:
use AmunCode\Config\EnvironmentLoader;
$environment = new EnvironmentLoader();
// Load .env if it exists.
$environment->load($root);By default, the .env file is optional. To require it:
$environment->load($root, requiredFile: true);When the file is required but does not exist, an exception is thrown.
Environment variables must be loaded before PHP configuration files are initialized, especially when those files use Env::get().
The recommended initialization order is:
- Load the Composer autoloader.
- Load environment variables using
EnvironmentLoader. - Initialize
Configto load PHP configuration files. - Access configuration values.
For example, consider this project structure:
project/
├── .env
├── config/
│ └── app.php
├── public/
│ └── index.php
└── vendor/
Create config/app.php:
<?php
declare(strict_types=1);
use AmunCode\Config\Env;
return [
'name' => Env::get('APP_NAME', 'My Application'),
'debug' => Env::get('APP_DEBUG', false),
'environment' => Env::get('APP_ENV', 'production'),
];Then initialize everything in public/index.php:
<?php
declare(strict_types=1);
use AmunCode\Config\Config;
use AmunCode\Config\EnvironmentLoader;
$root = dirname(__DIR__);
// Load Composer autoloader.
require $root . '/vendor/autoload.php';
// Load environment variables first.
$environment = new EnvironmentLoader();
$environment->load($root);
// Load PHP configuration files.
$config = new Config($root . '/config');
// Access configuration values.
$appName = $config->get('app.name');
$debug = $config->get('app.debug');The Config class does not automatically load the .env file. Environment initialization is an explicit step handled by EnvironmentLoader. Following this order ensures that environment variables are available when PHP configuration files are loaded.
EnvironmentLoader loads a .env file from a directory using vlucas/phpdotenv.
use AmunCode\Config\EnvironmentLoader;
$environment = new EnvironmentLoader();
// Optional: no exception is thrown if the .env file is absent.
$environment->load('/path/to/project');
// Required: throws if the .env file is absent or cannot be loaded.
$environment->load('/path/to/project', requiredFile: true);
// Check whether this instance completed loading.
$loaded = $environment->isLoaded();The load() method accepts:
| Parameter | Type | Default | Description |
|---|---|---|---|
$path |
string |
— | Directory containing the .env file. |
$requiredFile |
bool |
false |
When true, the .env file is required. When false, a missing file is allowed. |
A single EnvironmentLoader instance loads at most once. Calling load() again with the same resolved directory does nothing. Calling it with a different directory after a successful load throws a LogicException. The isLoaded() method reports the state of that instance; it does not report whether another instance or another part of the process loaded environment variables.
The loader uses Dotenv's immutable repository. Existing environment values are not overwritten by values from the .env file. It does not use putenv().
Use Env::get() to retrieve an environment value:
use AmunCode\Config\Env;
$appName = Env::get('APP_NAME', 'AmunCode');
$debug = Env::get('APP_DEBUG', false);
$databaseUrl = Env::get('DATABASE_URL');Environment lookup follows this order:
$_ENV$_SERVERgetenv()
The first source containing the key takes precedence. The default is returned only when the variable is missing. An existing empty string or null value is preserved.
Env::get() accepts a lazy default using a closure. The closure is evaluated only when the variable is missing:
$databaseName = Env::get(
'DB_DATABASE',
static fn (): string => 'application_default'
);Use Env::has() to check whether a variable exists in any supported source:
if (Env::has('APP_KEY')) {
// APP_KEY exists, even if its value is an empty string or null.
}String values are normalized case-insensitively for the following representations:
| Environment value | Result |
|---|---|
true or (true) |
true |
false or (false) |
false |
null or (null) |
null |
empty or (empty) |
'' |
0 |
'0' |
| An empty value | '' |
Other string values are returned unchanged. Non-string values are also returned unchanged.
Config loads PHP files directly inside the configuration directory. Each file must return an array. The filename, without the .php extension, becomes the top-level configuration key.
For example:
project/
├── config/
│ ├── app.php
│ ├── database.php
│ └── services.php
└── public/
└── index.php
config/app.php:
<?php
declare(strict_types=1);
use AmunCode\Config\Env;
return [
'name' => Env::get('APP_NAME', 'AmunCode'),
'debug' => Env::get('APP_DEBUG', false),
];config/database.php:
<?php
declare(strict_types=1);
use AmunCode\Config\Env;
return [
'driver' => Env::get('DB_CONNECTION', 'mysql'),
'host' => Env::get('DB_HOST', '127.0.0.1'),
'port' => Env::get('DB_PORT', '3306'),
'database' => Env::get('DB_DATABASE'),
'username' => Env::get('DB_USERNAME'),
'password' => Env::get('DB_PASSWORD'),
];After loading the environment, initialize the configuration:
$environment = new EnvironmentLoader();
$environment->load($root);
$config = new Config($root . '/config');
$config->get('app.name'); // AmunCode
$config->get('database.host'); // 127.0.0.1Files are loaded in filename order. Files in subdirectories are not loaded. A configuration file that does not return an array causes an UnexpectedValueException. A missing configuration directory causes an InvalidArgumentException.
Use dot notation to retrieve nested values:
$config->get('app.name');
$config->get('database.host');Pass a default for missing or invalid keys:
$config->get('cache.default', 'file');Call get() without a key to retrieve the complete configuration array:
$all = $config->get();An existing key with a null value is different from a missing key. In that case, get() returns null, not the supplied default.
Pass a string key to set or replace a value. Dot notation creates intermediate arrays when necessary:
$config->set('app.name', 'My Application');
$config->set('database.options.timeout', 10);Pass an array to set() to merge values into the existing configuration:
$config->set([
'app' => [
'debug' => true,
'timezone' => 'Africa/Cairo',
],
]);Array input uses PHP's array_replace_recursive() behavior. Existing string keys are replaced recursively. Numeric keys are replaced by index; this operation does not append numeric values.
The package exposes Env::get() and does not define a global env() function automatically. Applications that prefer a global helper can define one in their own support file:
<?php
declare(strict_types=1);
use AmunCode\Config\Env;
if (!function_exists('env')) {
function env(string $key, mixed $default = null): mixed
{
return Env::get($key, $default);
}
}This keeps the package independent of an application's global helper conventions.
Install the development dependencies:
composer installRun the PHPUnit suite:
vendor/bin/phpunitThe tests cover configuration retrieval and mutation, PHP configuration file loading, environment lookup and normalization, optional and required .env loading, and the environment/configuration loading lifecycle.
AmunCode Config is open-sourced software licensed under the MIT License.