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

Getting Started

Minimal Setup

  1. Installation: Add the package via Composer:

    composer require chillerlan/php-settings-container
    

    Requires PHP 8.4+.

  2. Basic Container Class: Create a class extending SettingsContainerAbstract:

    use Chillerlan\SettingsContainer\SettingsContainerAbstract;
    
    class AppSettings extends SettingsContainerAbstract {
        protected string $appName;
        protected string $environment;
        protected int $debugMode = 0;
    }
    
  3. First Use Case: Initialize with settings (array, JSON, or empty):

    $settings = new AppSettings([
        'appName' => 'MyApp',
        'environment' => 'production',
        'debugMode' => 1
    ]);
    
    // Access values
    echo $settings->appName; // "MyApp"
    

Key First Steps

  • Immutable Properties: All declared properties are immutable by default (no direct modification).
  • Magic Methods: Use get_/set_ prefixed methods for custom logic (e.g., get_debugMode()).
  • Serialization: Convert to/from JSON/arrays with toJSON()/fromJSON() or toArray().

Implementation Patterns

1. Configuration Management

Workflow:

  • Centralize app/config settings in a single container.
  • Example: Database, API keys, feature flags.
    class DatabaseConfig extends SettingsContainerAbstract {
        protected string $host;
        protected int $port;
        protected string $username;
        protected string $password;
    
        protected function DatabaseConfig(): void {
            $this->password = password_hash($this->password, PASSWORD_DEFAULT);
        }
    }
    

Integration with Laravel:

  • Load from .env in bootstrap/app.php:
    $databaseConfig = new DatabaseConfig([
        'host' => env('DB_HOST'),
        'port' => env('DB_PORT'),
        'username' => env('DB_USERNAME'),
        'password' => env('DB_PASSWORD'),
    ]);
    

2. Trait-Based Extensibility

Pattern: Combine traits from libraries/modules into one container.

  • Example: Merge MailSettings and CacheSettings traits:
    class AppConfig extends SettingsContainerAbstract {
        use MailSettings, CacheSettings;
    
        protected function MailSettings(): void {
            $this->mailFrom = strtolower($this->mailFrom);
        }
    }
    

3. Validation & Defaults

Pattern: Use set_ methods for validation or defaults.

  • Example: Enforce non-empty strings:
    protected function set_appName(string $value): void {
        if (empty($value)) {
            throw new \InvalidArgumentException("App name cannot be empty");
        }
        $this->appName = $value;
    }
    

4. Dependency Injection

Pattern: Bind container to Laravel’s service container:

// In a service provider
$this->app->singleton('config', function ($app) {
    return new AppSettings([
        'appName' => config('app.name'),
        'debugMode' => config('app.debug'),
    ]);
});

Usage in Controllers:

public function __construct(private AppSettings $settings) {}

5. Environment-Specific Configs

Pattern: Load different configs per environment.

  • Example: Override debugMode in AppServiceProvider:
    $settings = app('config');
    $settings->fromIterable([
        'debugMode' => app()->environment('local') ? 1 : 0,
    ]);
    

Gotchas and Tips

1. Property Hooks (PHP 8.4+)

  • Gotcha: Property hooks (PHP 8.4+) take precedence over magic get_/set_ methods.

    • If a property has a hook (e.g., protected string $foo { set => ... }), the magic method is ignored.
    • Use hasSetHook()/hasGetHook() to debug conflicts.
  • Tip: Use hooks for simple transformations (e.g., auto-trimming strings):

    protected string $name { set => trim($value); }
    

2. Invalid Property Handling

  • Gotcha: By default, accessing undefined properties returns null.
    • Enable strict mode with [ThrowOnInvalidProperty(true)]:
      #[ThrowOnInvalidProperty(true)]
      class AppSettings extends SettingsContainerAbstract { ... }
      
    • Now $settings->nonexistent throws InvalidPropertyException.

3. Serialization Quirks

  • Gotcha: serialize()/unserialize() bypass magic methods/property hooks.
    • Use toArray()/fromIterable() for consistent behavior:
      $serialized = serialize($settings->toArray());
      $restored = new AppSettings();
      $restored->fromIterable(unserialize($serialized));
      

4. Trait Initialization Order

  • Gotcha: Traits are initialized in declaration order (LIFO).
    • Example: If TraitA and TraitB are used, TraitB::TraitB() runs first.
    • Fix: Explicitly call trait methods in construct():
      protected function construct(): void {
          $this->TraitA();
          $this->TraitB();
      }
      

5. JSON/Array Conversion

  • Tip: toArray() now respects magic getters (since v3.2.0).
    • Example: Custom getters in arrays:
      $settings->toArray(); // Calls get_debugMode(), not direct property access
      

6. Performance Considerations

  • Tip: Avoid overusing magic methods for simple getters/setters.
    • Prefer property hooks (PHP 8.4+) or direct properties for performance-critical paths.

7. Debugging

  • Tip: Use get_object_vars() to inspect raw properties (bypasses magic methods):
    print_r(get_object_vars($settings)); // Shows unprocessed values
    

8. Laravel-Specific Tips

  • Tip: Cache the container instance to avoid re-parsing configs:
    $this->app->singleton('config', fn() => new AppSettings(config('app.settings')));
    
  • Gotcha: Avoid circular dependencies when binding containers to the service container.

9. Extending the Container

  • Tip: Create a base container class for your app:
    abstract class BaseSettings extends SettingsContainerAbstract {
        protected function construct(): void {
            // Shared logic (e.g., logging, validation)
        }
    }
    
    Extend this for all app-specific containers.

10. Testing

  • Tip: Mock the container in tests:
    $mockSettings = $this->createMock(AppSettings::class);
    $mockSettings->method('toArray')->willReturn(['debugMode' => 1]);
    
  • Gotcha: Use fromIterable() to reset test state:
    $settings->fromIterable([]); // Reset to defaults
    
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi