sandrokeil/interop-config
Framework-agnostic PHP library for configuration-driven factories. Validates config structure, merges defaults, enforces required options, reduces factory boilerplate, supports auto-discovery of factories, and can generate configuration files from factory classes.
Installation (PHP 8+ required):
composer require sandrokeil/interop-config
Add to composer.json under require if not auto-loaded.
First Look:
InteropConfig\ConfigInterface, InteropConfig\Config, InteropConfig\FactoryInterface.src/Config.php, src/Factory.php (check vendor/sandrokeil/interop-config).First Use Case (unchanged):
Define a config structure (e.g., config/my_module.php):
return [
'required_option' => env('REQUIRED_VALUE', 'default'),
'optional' => [
'nested' => 'value',
],
];
Create a factory class (e.g., app/Modules/MyModule/MyModuleFactory):
use InteropConfig\FactoryInterface;
class MyModuleFactory implements FactoryInterface {
public function create(array $config) {
return new MyModule($config['required_option'], $config['optional'] ?? []);
}
}
Register the factory in a service provider:
$this->app->bind('my.module', function ($app) {
return $app->make(FactoryInterface::class)
->create(config('my_module'));
});
Config-Driven Instantiation (unchanged):
Config class to enforce structure and validate mandatory fields:
$config = new \InteropConfig\Config([
'required' => 'value',
'optional' => null,
], ['required']); // 'required' is mandatory
Factory Integration (unchanged):
FactoryInterface for custom logic:
class UserFactory implements FactoryInterface {
public function create(array $config) {
return new User(
$config['name'],
$config['email'] ?? 'default@example.com'
);
}
}
Uniform Config Structure (unchanged):
Config class.$config = new \InteropConfig\Config($rawConfig, [
'users.*' => ['name', 'email'], // Mandatory for each user
]);
public function boot() {
$this->app->singleton(FactoryInterface::class, function ($app) {
return new MyModuleFactory();
});
}
Config::validate() for runtime checks (e.g., API payloads):
$validated = \InteropConfig\Config::validate($request->all(), ['required_field']);
FactoryInterface to test instantiation logic:
$factory = Mockery::mock(FactoryInterface::class);
$factory->shouldReceive('create')->once()->andReturn(new MyClass());
$this->app->instance(FactoryInterface::class, $factory);
Mandatory Field Validation (unchanged):
Config constructor throws InvalidArgumentException.Config:
new \InteropConfig\Config($data, ['key1', 'key2.nested']);
Nested Array Handling (unchanged):
users.*.email) require precise dot notation.Config::validate() with recursive checks:
$config = \InteropConfig\Config::validate($data, [
'users.*' => ['email', 'name'],
]);
Factory Binding Overrides (unchanged):
when() or unless() in service providers for conditional binding.Legacy Configs (unchanged):
Config instantiation.The "required_key" key is required in the config.
dd($config) inside create() to inspect passed data.Config by overriding validate() or adding static methods. Leverage PHP 8 features like named arguments:
class ExtendedConfig extends \InteropConfig\Config {
public static function validateEmail(array $data, string $field = 'email') {
return self::validate($data, [$field]);
}
}
$this->app->bind('dynamic.factory', fn(array $config) => new DynamicClass($config));
$merged = array_merge(
config('default'),
cache('custom_config')
);
$config = new \InteropConfig\Config($merged, ['required']);
Config or FactoryInterface:
class MyFactory implements FactoryInterface {
public function __construct(private array $defaultConfig) {}
public function create(array $config) {
return new MyClass(array_merge($this->defaultConfig, $config));
}
}
$config = new \InteropConfig\Config(
$data,
requiredFields: ['required_key'],
optionalFields: ['optional_key']
);
How can I help you explore Laravel packages today?