Weave Code
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

Php Settings Container Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Immutable Configuration Pattern: The package excels at enforcing immutable settings objects, aligning well with Laravel’s configuration management (e.g., config() helper). It replaces mutable arrays with typed, structured objects, reducing runtime errors from invalid keys.
  • Trait-Based Composition: Supports modular configuration via traits (e.g., SomeOptions, MoreOptions), enabling reusable, library-agnostic settings blocks. This mirrors Laravel’s service provider pattern but for configuration.
  • Property Hooks (PHP 8.4+): Leverages native PHP 8.4 property hooks for getters/setters, avoiding magic methods where possible. Laravel’s config() uses arrays under the hood; this package offers a more structured alternative.
  • Serialization/Deserialization: Implements JsonSerializable, Serializable, and manual toArray()/fromJSON(), making it compatible with Laravel’s caching (e.g., cache()->put()) and API responses.

Integration Feasibility

  • Laravel Configuration System:
    • Replace config('app.timezone') with $settings->timezone (if using a SettingsContainer).
    • Bind the container to Laravel’s IoC via bind('settings', fn() => new AppSettings()) for dependency injection.
  • Environment Overrides:
    • Use .env to populate the container during bootstrap (e.g., new AppSettings($_ENV)).
    • Validate .env keys against the container’s properties (e.g., via #[ThrowOnInvalidProperty]).
  • Service Providers:
    • Register the container in AppServiceProvider::boot() and merge it with Laravel’s config array for backward compatibility:
      $this->app->singleton('settings', fn() => new AppSettings(config('app.settings')));
      

Technical Risk

  • PHP 8.4 Dependency: Blocks use in older Laravel versions (e.g., LTS 8.x). Mitigation: Polyfill property hooks or use a fork like php-settings-container-legacy.
  • Magic Methods vs. Explicit Typing:
    • Risk of runtime errors if traits/properties conflict (e.g., set_foo() vs. PHP 8.4 property hooks).
    • Mitigation: Use hasSetHook()/hasGetHook() checks in custom logic.
  • Performance Overhead:
    • Magic __get()/__set() may add microsecond latency. Benchmark against Laravel’s array-based config.
    • Mitigation: Profile in production; cache serialized containers if used frequently.

Key Questions

  1. Backward Compatibility:
    • How will existing config('key') calls transition to $settings->key? Use a facade or alias?
  2. Validation:
    • Should the container validate .env values against property types (e.g., string $timezone)?
  3. Caching:
    • Can the container replace Laravel’s config cache? Yes, but requires custom cache driver integration.
  4. Testing:
    • How to mock the container in PHPUnit? Use partialMockBuilder() or a test double.
  5. Migration Path:
    • Start with non-critical settings (e.g., logging, caching) before core app config.

Integration Approach

Stack Fit

  • Laravel Core:
    • Replace config() for new projects or incrementally migrate settings.
    • Use the container as a single source of truth for app-wide configuration (e.g., replace config('app.*')).
  • Laravel Packages:
    • Ideal for packages needing structured configs (e.g., spatie/laravel-permission could use SettingsContainer for role/permission defaults).
  • APIs:
    • Return container instances in API responses (via toArray()) for consistency.
  • Queues/Jobs:
    • Pass container instances to jobs for immutable configuration (e.g., new ProcessPayment($settings)).

Migration Path

  1. Phase 1: New Features
    • Use the container for new configuration (e.g., feature flags, third-party API settings).
    • Example:
      class FeatureFlags extends SettingsContainerAbstract {
          use FeatureFlagsTrait;
      }
      
  2. Phase 2: Incremental Replacement
    • Replace config('app.*') with a AppSettings container bound to the IoC.
    • Use a facade for backward compatibility:
      facade('Settings', fn() => $app->make('settings'));
      
  3. Phase 3: Full Migration
    • Deprecate config('app.*') in favor of $settings->key.
    • Update .env validation to match container properties.

Compatibility

  • Laravel Config:
    • Merge container data with Laravel’s config array during bootstrap:
      config(['app.timezone' => $settings->timezone]);
      
  • Environment Variables:
    • Use vlucas/phpdotenv to load .env into an array, then pass to the container:
      $settings = new AppSettings($_ENV);
      
  • Validation:
    • Integrate with Laravel’s validator:
      $validator = Validator::make($_ENV, [
          'APP_TIMEZONE' => ['required', 'string'],
          'DB_CONNECTION' => ['required', 'in:mysql,pgsql'],
      ]);
      

Sequencing

  1. Bootstrap:
    • Load the container after Laravel’s config is initialized but before service providers.
    • Example in bootstrap/app.php:
      $settings = new AppSettings($_ENV);
      $app->singleton('settings', fn() => $settings);
      
  2. Service Providers:
    • Register the container as a singleton and bind it to interfaces.
  3. Middleware/Facades:
    • Create a Settings facade for global access:
      Settings::get('timezone');
      
  4. Testing:
    • Mock the container in tests using Laravel’s MockApplication.

Operational Impact

Maintenance

  • Pros:
    • Type Safety: Properties are typed (e.g., string $timezone), reducing runtime errors.
    • Immutability: Prevents accidental config overrides in long-running processes (e.g., queues).
    • Modularity: Traits enable reusable settings blocks (e.g., DatabaseSettings, CacheSettings).
  • Cons:
    • Boilerplate: Requires defining classes/traits for each settings group.
    • Debugging: Magic __get()/__set() can obscure stack traces. Use #[ThrowOnInvalidProperty] to fail fast.
  • Tooling:
    • Use PHPStan with the provided rules-magic-access.neon to suppress false positives.
    • Integrate with Laravel Scout for searching config values.

Support

  • Documentation:
    • Add a Settings section to Laravel’s docs explaining migration from config().
    • Example:
      ## Migrating to Settings Container
      Replace:
      ```php
      config('app.timezone');
      
      With:
      Settings::timezone();
      
  • Troubleshooting:
    • Common issues:
      • Property hooks vs. magic methods conflicts (use hasSetHook() checks).
      • .env keys not matching container properties (validate early).
    • Debug with:
      $settings->toArray(); // Inspect current state
      

Scaling

  • Performance:
    • Cold Start: Container initialization adds ~1–5ms (benchmark with microtime()).
    • Hot Paths: Cache serialized containers in Redis for high-frequency access:
      $cached = cache()->remember('settings', 60, fn() => $settings->toJSON());
      
  • Distributed Systems:
    • Use Laravel Horizon to broadcast config changes to queues/workers.
    • For microservices, expose the container via Laravel Sanctum or gRPC.

Failure Modes

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

Ramp-Up

  • Developer Onboarding:
    • Training: 30-minute session on:
      • Defining SettingsContainer classes.
      • Migrating from config() to $settings->key.
      • Using traits for modularity.
    • Cheat Sheet:
      ## Settings Container Quick Start
      1. Define a container:
         ```php
         class AppSettings extends SettingsContainerAbstract {
             protected string $timezone;
             protected int $maxRetries;
         }
      
      1. Populate from .env:
        $
        
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope