-
Notifications
You must be signed in to change notification settings - Fork 0
Recipe Typed Config Class
Goal: define application configuration as a typed PHP class so you
get IDE autocompletion, static-analysis coverage, and a single source of
truth — while still reading it through the uniform
ConfigInterface API.
Extend Classes and declare your settings as
public properties with defaults:
namespace App\Config;
use InitPHP\Config\Classes;
final class AppConfig extends Classes
{
public string $name = 'InitPHP App';
public string $env = 'production';
public bool $debug = false;
public string $timezone = 'UTC';
/** @var array<string, mixed> */
public array $db = [
'host' => '127.0.0.1',
'port' => 3306,
'name' => 'app',
'charset' => 'utf8mb4',
];
/** @var array<string, mixed> */
public array $cache = [
'driver' => 'file',
'ttl' => 3600,
];
}use App\Config\AppConfig;
$config = new AppConfig();
$config->get('name'); // 'InitPHP App'
$config->get('db.host'); // '127.0.0.1'
$config->get('db.port'); // 3306
$config->get('cache.driver'); // 'file'
$config->has('db.charset'); // true
$config->get('db.ssl', false); // false (default — key absent)Nested array properties become dotted paths automatically; see Keys & Dotted Paths.
Because a config class shares the full read/write surface, you can adjust values after construction — handy for tests or per-request tweaks:
$config->set('debug', true);
$config->set('db.host', 'db.internal');
$config->get('debug'); // true
$config->get('db.host'); // 'db.internal'Type-hint against the interface so consumers stay decoupled and testable:
use InitPHP\Config\Interfaces\ConfigInterface;
use App\Config\AppConfig;
$container->set(ConfigInterface::class, fn () => new AppConfig());
final class Mailer
{
public function __construct(private ConfigInterface $config) {}
public function fromAddress(): string
{
return $this->config->get('mail.from', 'no-reply@example.com');
}
}In a test, pass any ConfigInterface — including a plain
Library seeded with just the keys under test:
use InitPHP\Config\Library;
$mailer = new Mailer(new Library(['mail' => ['from' => 'test@example.com']]));
$mailer->fromAddress(); // 'test@example.com'Classes imports public and protected property defaults (not
private). Use a protected property for a value you want available as
config but not as part of the public class surface:
final class AppConfig extends Classes
{
public string $name = 'InitPHP App';
protected string $secret = 'shared-internally'; // imported as 'secret'
private string $token = 'never-imported'; // NOT imported
}See Configuration Classes → What gets imported.
| Typed class | File / directory loaders |
|---|---|
| Config known at author time | Config supplied by ops / env |
| Autocompletion + static analysis | Dynamic, discovered at runtime |
| One class, version-controlled | Many files, environment overrides |
The two compose well: define stable defaults as a class, and layer
runtime overrides with a Library when needed.
- Configuration Classes
- The Library Object — for runtime/injected config.
- Environment-Aware Config — file-based overrides.
initphp/config · MIT License · part of the InitPHP family
Source · Issues · Discussions · Packagist · Contributing · Security Policy
Getting Started
Core Concepts
Loading Configuration
Reference
Practical Guides
Migration & Help