chillerlan/php-settings-container
Lightweight PHP settings container to keep configuration logic out of your app (not a DI container). Provides a SettingsContainerInterface with “property hook”-style access for PHP < 8.4, plus sane defaults for organizing and retrieving settings objects.
config() helper). It replaces mutable arrays with typed, structured objects, reducing runtime errors from invalid keys.SomeOptions, MoreOptions), enabling reusable, library-agnostic settings blocks. This mirrors Laravel’s service provider pattern but for configuration.config() uses arrays under the hood; this package offers a more structured alternative.JsonSerializable, Serializable, and manual toArray()/fromJSON(), making it compatible with Laravel’s caching (e.g., cache()->put()) and API responses.config('app.timezone') with $settings->timezone (if using a SettingsContainer).bind('settings', fn() => new AppSettings()) for dependency injection..env to populate the container during bootstrap (e.g., new AppSettings($_ENV))..env keys against the container’s properties (e.g., via #[ThrowOnInvalidProperty]).AppServiceProvider::boot() and merge it with Laravel’s config array for backward compatibility:
$this->app->singleton('settings', fn() => new AppSettings(config('app.settings')));
set_foo() vs. PHP 8.4 property hooks).hasSetHook()/hasGetHook() checks in custom logic.__get()/__set() may add microsecond latency. Benchmark against Laravel’s array-based config.config('key') calls transition to $settings->key? Use a facade or alias?.env values against property types (e.g., string $timezone)?partialMockBuilder() or a test double.config() for new projects or incrementally migrate settings.config('app.*')).spatie/laravel-permission could use SettingsContainer for role/permission defaults).toArray()) for consistency.new ProcessPayment($settings)).class FeatureFlags extends SettingsContainerAbstract {
use FeatureFlagsTrait;
}
config('app.*') with a AppSettings container bound to the IoC.facade('Settings', fn() => $app->make('settings'));
config('app.*') in favor of $settings->key..env validation to match container properties.config(['app.timezone' => $settings->timezone]);
vlucas/phpdotenv to load .env into an array, then pass to the container:
$settings = new AppSettings($_ENV);
$validator = Validator::make($_ENV, [
'APP_TIMEZONE' => ['required', 'string'],
'DB_CONNECTION' => ['required', 'in:mysql,pgsql'],
]);
bootstrap/app.php:
$settings = new AppSettings($_ENV);
$app->singleton('settings', fn() => $settings);
Settings facade for global access:
Settings::get('timezone');
MockApplication.string $timezone), reducing runtime errors.DatabaseSettings, CacheSettings).__get()/__set() can obscure stack traces. Use #[ThrowOnInvalidProperty] to fail fast.rules-magic-access.neon to suppress false positives.Settings section to Laravel’s docs explaining migration from config().## Migrating to Settings Container
Replace:
```php
config('app.timezone');
With:
Settings::timezone();
hasSetHook() checks)..env keys not matching container properties (validate early).$settings->toArray(); // Inspect current state
microtime()).$cached = cache()->remember('settings', 60, fn() => $settings->toJSON());
| Scenario | Impact | Mitigation |
|---|---|---|
Invalid .env key |
Silent null or exception |
Use #[ThrowOnInvalidProperty] |
| Property hook conflicts | Unexpected getter/setter behavior | Check hasSetHook() before calling |
| Serialization errors | Corrupted cached data | Validate json_decode() results |
| PHP 8.4 downgrade | Property hooks break | Use a polyfill or legacy fork |
SettingsContainer classes.config() to $settings->key.## Settings Container Quick Start
1. Define a container:
```php
class AppSettings extends SettingsContainerAbstract {
protected string $timezone;
protected int $maxRetries;
}
.env:
$
How can I help you explore Laravel packages today?