Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Config Laravel Package

illuminate/config

Laravel's configuration component provides a repository for loading PHP config files, accessing values with dot notation, setting defaults, and managing environment-specific overrides. It powers Laravel's config system and can be used standalone in any PHP project.

View on GitHub
Deep Wiki
Context7

Getting Started

Install

composer require illuminate/config

This pulls in illuminate/collections and illuminate/contracts (plus psr/container). Pin to a single Laravel major — illuminate/config:^11 with illuminate/collections:^12 will trip over missing methods. PHP 8.2+ for v11/v12, 8.3+ for v13.

Inside a Laravel app you already have it: use the Config facade, the config() helper, or resolve Illuminate\Contracts\Config\Repository from the container. The package is only relevant directly when you're building something outside Laravel.

First stop: read src/Repository.php. The entire package is basically that one class (~200 lines). Everything else is a subtree-split artifact. Pair it with the Laravel Configuration docs — the public API is identical, only the bootstrapping is missing.

First use case: replace scattered define()s / included arrays with one dot-addressable bag.

use Illuminate\Config\Repository;

$config = new Repository([
    'app'      => ['name' => 'MyApp', 'debug' => true],
    'database' => ['default' => 'mysql', 'connections' => ['mysql' => ['host' => '127.0.0.1']]],
]);

$config->get('app.name');                      // "MyApp"
$config->get('database.connections.mysql.host'); // "127.0.0.1"
$config->get('cache.driver', 'array');         // "array" (default)

That's it. No container, no service provider, no auto-discovery. You own loading, environment handling, and caching.

Implementation Patterns

Load config files the way Laravel's LoadConfiguration bootstrapper does — scan a directory, key by basename, set() the return value:

$config = new Repository();

foreach (glob(__DIR__ . '/config/*.php') as $path) {
    $config->set(basename($path, '.php'), require $path);
}

That single loop is 90% of what full-framework Laravel does at boot.

Environment overrides without Laravel. Add vlucas/phpdotenv, load .env into $_ENV, then merge a per-environment directory over the base one:

$env = $_ENV['APP_ENV'] ?? 'production';

foreach (glob(__DIR__ . "/config/{$env}/*.php") as $path) {
    $key = basename($path, '.php');
    $config->set($key, array_replace_recursive($config->get($key, []), require $path));
}

Inside the config files themselves, read $_ENV['DB_HOST'] ?? 'localhost' — there is no env() helper here unless you bring illuminate/support.

Roll your own config:cache. serialize($config->all()) or var_export() to a PHP file, then on boot:

$cached = __DIR__ . '/storage/config.php';
$config = new Repository(is_file($cached) ? require $cached : []);

Invalidate by comparing a hash of every config file's mtime. Skip this until boot time actually hurts — file reads are cheap and cached config is a common source of "why didn't my change take effect" bugs.

Type-hint against the contract, not the class. Illuminate\Contracts\Config\Repository gives you get/set/has/all/forget without dragging the concrete class into signatures. Makes it trivial to swap in a test double.

Runtime mutation is a first-class workflow. set() for per-request/per-test overrides, push()/prepend() when a module wants to append to an existing array (middleware lists, allowed drivers, feature flags), forget() when a later layer wins:

$config->push('app.providers', ReportingServiceProvider::class);
$config->forget('app.debug');       // also accepts an array of keys
$config->set('services.mailgun.domain', 'mg.example.com');

ArrayAccess is supported but get() is the idiomatic read. $config['app.name'] works; $config->get('app.name', $default) is what you actually want most of the time.

Testing pattern: build a fresh Repository per test containing only the keys under test. Don't share a global instance — mutation from one test leaks into the next.

protected function setUp(): void
{
    $this->config = new Repository([
        'queue' => ['driver' => 'sync', 'retry' => 3],
    ]);
}

Lazy loading, if you want it, is yours to implement: the class is just an array wrapper, so subclass it and override get()/has()/offsetGet() to defer an expensive load (DB, remote config service) until a specific namespace is first touched. There is no built-in loader mechanism to hook into.

Gotchas and Tips

  • The constructor signature has changed. Older tutorials (and some generated notes) show new Repository($loader, $environment) with FileLoader / LoaderInterface / ArrayLoader. Those classes were removed in Laravel 5.3. Current versions take array $items = [] and nothing else. If you copy a snippet with a loader, it will fail with "too many arguments" or "class not found."

  • No .env parsing. env() lives in illuminate/support, not here. Config files that call env() directly will fatal error unless you install and load support/dotenv yourself.

  • No caching. config:cache is an artisan command in illuminate/framework, not a feature of this package. The Repository keeps everything in memory and never touches disk.

  • No auto-discovery, no service provider, no bootstrapper. You construct it, you point it at files, you register it. There's no ConfigServiceProvider to find.

  • get() returns null for both "missing" and "explicitly null." Use has() (Arr::has) when that distinction matters — it's the only way to tell 'app.debug' => null from 'app.debug' => absent.

  • Dot-notation is a double-edged sword on set(). set('a.b', 1) builds a nested array. If you later need a literal key containing a dot, you can't reach it — the dot is always interpreted as nesting. Avoid literal dots in config keys.

  • offsetGet / ArrayAccess silently returns null for missing keys and does not throw or support defaults. $config['missing'] is a quiet bug factory; prefer get() with an explicit default.

  • all() is a shallow snapshot. Nested arrays are copied on write (safe), but any objects inside config values are shared references. If a config file returns a new Something(), every caller gets the same instance and can mutate it.

  • var_export() caching breaks on closures and objects. Some third-party packages ship config files returning closures. serialize() handles closures badly too (fails) and requires the class to be autoloadable at read time. Restrict cached config to scalars/arrays or use serialize() and accept the constraints.

  • Debugging is trivial because the class is tiny. get() delegates to Arr::get($this->items, $key, $default) — if a lookup fails, it's virtually always a nesting mismatch or a stale cached file, not a bug in the package. Dump $config->all() and trace the dotted path by hand.

  • Extension points are your own. If you need JSON/YAML/DB loaders, schema validation, or read-through caching, decorate Repository or subclass it — don't wait for LoaderInterface to come back. The contract has only has/get/set/prepend/push/all/forget, which is a small surface to wrap.

  • This repo is a read-only subtree split of laravel/framework. Issues and PRs filed here go nowhere useful; the real source of truth — and the real changelog — is the monorepo. Track security patches by tracking Laravel core releases, not this repo's tags.

  • Zero dependents on Packagist is not a red flag here — it's a split artifact, not an independently versioned library. But it does mean you're on the hook for documenting your own bootstrap, because there isn't much beyond the docs page.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
alesima/laravel-azure-service-bus
tomshaw/shopcart
likyly/laravel
darthsoup/shoppingcart
tdt/core
labyrinthe/connect-php
encore2/laravel-admin2
cboxdk/laravel-console-kit
shapecode/doctrine-dbal-datetimeutc
gilads-otiannoh254/inertia-protocol
dakiquang/laravel-oauth-refresh-lock
woda/laravel-worktrees
dalefranks/ramasite
faghy/laracashbook
roundly-consulting/google-places-for-laravel
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel