dflydev/dot-access-configuration
PHP configuration library that stores settings as nested arrays and exposes them through simple dot-notation access. Build config from arrays, JSON, or YAML, merge multiple sources, and replace placeholders at build time for flexible, environment-aware application configuration.
Install the package and, for YAML configs, the YAML parser it needs:
composer require dflydev/dot-access-configuration
composer require symfony/yaml # only if you need YAML
Start with the README and these two classes:
Dflydev\DotAccessConfiguration\ConfigurationBuilder — imports files, applies overrides, and builds the config object.Dflydev\DotAccessConfiguration\Configuration — the dot-notation config object itself.The first practical use case is reading an external JSON/YAML file into a dot-notation object without touching Laravel’s native config repository:
use Dflydev\DotAccessConfiguration\ConfigurationBuilder;
use Dflydev\DotAccessConfiguration\Reader\YamlConfigurationReader;
$builder = new ConfigurationBuilder(new YamlConfigurationReader());
$builder->import(base_path('config/external.yaml'));
$config = $builder->build();
$host = $config->get('database.connections.mysql.host');
For JSON, the builder defaults to a JSON reader:
$builder = new ConfigurationBuilder();
$builder->import(base_path('config/external.json'));
$config = $builder->build();
Some versions expose a ConfigurationBuilder::fromFile() shortcut, but the explicit builder above works across versions and makes the reader obvious.
Import a base file, then an environment-specific file. Later imports override earlier scalar values and deep-merge associative arrays:
$builder = new ConfigurationBuilder(new YamlConfigurationReader());
$builder->import(base_path('config/app.yaml'));
$builder->import(base_path('config/app.'.app()->environment().'.yaml'));
$config = $builder->build();
This is the closest analogue to Laravel’s per-environment config files, but for files outside config/.
If the rest of the app should keep using config(), export the built configuration into Laravel config in a service provider:
use Dflydev\DotAccessConfiguration\ConfigurationBuilder;
public function register(): void
{
$config = ConfigurationBuilder::fromFile(
base_path('config/external.yaml')
)->build();
config(['external' => $config->export()]);
}
Then use native Laravel access:
config('external.database.connections.mysql.host');
Because this runs during application bootstrap, the merged values are included when php artisan config:cache runs.
When you want to keep the package’s API instead of flattening into Laravel config:
$this->app->singleton('external.config', function () {
return ConfigurationBuilder::fromFile(
base_path('config/external.yaml')
)->build();
});
Usage:
app('external.config')->get('features.new_dashboard');
The builder is mutable, so you can layer runtime values on top of file config:
$builder->set('feature.enabled', true);
$builder->append('queues', ['high', 'low']);
$config = $builder->build();
Use set() when you want to replace a key outright, and append() when you want merge semantics.
Configuration can be constructed directly from an array, which is useful in tests:
use Dflydev\DotAccessConfiguration\Configuration;
$config = new Configuration([
'foo' => ['bar' => 'baz'],
]);
$this->assertSame('baz', $config->get('foo.bar'));
$this->assertTrue($config->has('foo.bar'));
If you have INI, TOML, database-backed, or encrypted config, implement ConfigurationReaderInterface and pass it to the builder:
use Dflydev\DotAccessConfiguration\ConfigurationReaderInterface;
class TomlConfigurationReader implements ConfigurationReaderInterface
{
public function read(string $file): array
{
return parse_toml(file_get_contents($file));
}
}
Then:
$builder = new ConfigurationBuilder(new TomlConfigurationReader());
$builder->import(base_path('config/service.toml'));
This is the main extension point. The builder does not care where the array came from.
config('foo.bar') and Arr::get(). The package earns its place when you need file readers, imports, merge behavior, or a standalone configuration object that works outside Laravel.symfony/yaml. JSON works out of the box. If you get a “class not found” or parser error for YAML, check that dependency first.import() merges through dflydev/dot-access-data; associative arrays are deep-merged and later scalar values win. If you need to replace an entire array, use set() with the full array rather than assuming import() will overwrite it.base_path(...), storage_path(...), or another absolute path.config:cache. If you load files at runtime, Laravel’s config cache will not include them. Either merge into config() during a service provider’s register()/boot() so config:cache captures the result, or cache the exported array yourself.get() returns null for missing keys. Use has() when you need to distinguish “missing” from “explicitly null.”export(). When dot-notation access is surprising, dump $config->export() to see the full merged array and verify the import order.%database.host%, look at the companion dflydev/placeholder-resolver package rather than expecting this package to interpolate automatically.fromFile() signature. The explicit new ConfigurationBuilder($reader) plus import() pattern is the safest portable form; shortcut methods have varied slightly across releases.How can I help you explore Laravel packages today?