- Can I use this package to replace Laravel’s built-in config() helper entirely?
- No, but you can augment it. The package enforces immutability for settings objects, so it’s ideal for complex nested configurations (e.g., feature flags, API endpoints). For full replacement, wrap `config()` calls in a facade that converts arrays to `SettingsContainer` objects. Start with opt-in adoption for new features.
- How do I integrate this with Laravel’s service container?
- Bind your settings class as a singleton in a service provider. For example: `app()->bind(AppSettings::class, fn() => new AppSettings(config('app')))`. This keeps settings immutable while leveraging Laravel’s DI for initialization. Avoid mixing with Laravel’s built-in DI container for pure config use cases.
- Will this work with Laravel 9 or PHP 8.1?
- No, this package requires PHP 8.4+ due to property hooks. For older Laravel versions, use a polyfill like `chillerlan/php-settings-container-polyfill` or stick to the trait-based approach (without property hooks). Laravel 10+ is the minimum viable version for full feature support.
- How do I migrate from array-based config assertions to object assertions in tests?
- Replace `assertArrayHasKey()` with `assertObjectHasProperty()` or `assertInstanceOf(SettingsContainerInterface::class)`. For nested settings, use `assertSame()` to compare objects. Tools like Pest or PHPUnit support both styles, but object assertions are stricter and catch type mismatches early.
- Can I compose settings from multiple packages (e.g., AuthSettings + CacheSettings)?
- Yes, use traits to modularize settings. For example, create `AuthSettingsTrait` and `CacheSettingsTrait`, then compose them in a base class: `class AppSettings extends SettingsContainer { use AuthSettingsTrait, CacheSettingsTrait; }`. This aligns with Laravel’s modular architecture and avoids tight coupling.
- Does this package support Laravel’s config caching (config:cache)?
- Not natively, but you can implement a hybrid system. Cache the serialized array version of your settings (e.g., `Cache::remember('settings', fn() => SettingsContainer::fromArray(config('settings')))`), then hydrate the immutable object on demand. Avoid caching objects directly due to serialization risks.
- How do I handle dynamic property names (e.g., settings['dynamic_key'])?
- Use the `SettingsContainer` trait’s `offsetGet()`/`offsetSet()` methods for dynamic keys. For PHP 8.4+, property hooks enable advanced behavior like computed properties. Test dynamic access in isolation to avoid collisions with Laravel’s magic methods (e.g., Eloquent’s `getAttribute()`).
- What’s the performance impact of property hooks in high-traffic Laravel apps?
- Property hooks add minor overhead (~10-15% per access in microbenchmarks). For API routes, cache settings objects (e.g., `Cache::rememberForever()`) or use a hybrid array/object approach. Profile with Laravel’s built-in benchmarking tools to validate trade-offs for your workload.
- How do I validate settings objects against Laravel’s validation rules?
- Use Laravel’s `Validator` with custom rules. For example: `Validator::make($settings->toArray(), ['timeout' => 'integer|max:300'])` or extend `SettingsContainer` to include validation logic. Immutable objects prevent runtime mutations, making validation more predictable than with mutable arrays.
- Are there alternatives to this package for immutable Laravel config?
- For PHP 8.1+, consider `spatie/laravel-config-array` (array-based) or `league/container` (DI-focused). For strict immutability, `symfony/options-resolver` is another option, but it lacks property hooks. This package is unique for its trait-based composition and PHP 8.4+ property hooks, ideal for complex, typed settings.