coshi/variator
Generate all combinations of parameter values from a simple config array. Supports enums, integer ranges, callbacks/functions, and cross-referenced variations between fields. Iterate results as arrays keyed by parameter name for easy testing or data generation.
composer require coshi/variator
use Coshi\Variator\VariationFactory;
use Coshi\Variator\VariationsTreeBuilder;
$factory = new VariationFactory();
$builder = new VariationsTreeBuilder($factory);
$config = [
'status' => ['type' => 'enum', 'values' => ['active', 'inactive']],
'priority' => ['type' => 'int', 'min' => 1, 'max' => 3],
];
$variations = $builder->build($config);
VariationsTreeBuilder: Core class for building variations.VariationFactory: Handles value generation logic.enum, int, callback, and cross-referencing.Data Seeding: Generate test data for Laravel factories:
$builder->build($config); // Returns array of combinations
foreach ($variations as $data) {
Model::factory()->create($data);
}
Dynamic Test Cases: Use in PHPUnit tests for parameterized test data:
$variations = $builder->build($config);
foreach ($variations as $data) {
$this->assertSomething($data);
}
API Response Variations: Simulate different API responses for testing:
$responses = $builder->build([
'status' => ['type' => 'enum', 'values' => [200, 404, 500]],
'data' => ['type' => 'callback', 'callback' => [MockData::class, 'generate']],
]);
Laravel Service Provider:
Bind VariationsTreeBuilder to the container for easy access:
$this->app->bind(VariationsTreeBuilder::class, function ($app) {
return new VariationsTreeBuilder(new VariationFactory());
});
Usage:
$builder = app(VariationsTreeBuilder::class);
Dynamic Configs: Load configs from JSON/YAML files for reusability:
$config = json_decode(file_get_contents('variations.json'), true);
$builder->build($config);
Cross-Referencing:
Use @key syntax for context-dependent values (e.g., @status):
'priority' => [
'type' => 'callback',
'callback' => [PriorityLogic::class, 'getPriorities'],
'context_dependent' => true,
],
Callback Context:
context_dependent: true for callbacks with @key references will throw errors.'callback' => [Class::class, 'method', ['@status']], // Requires context_dependent
Type Validation:
int/float ranges must have min <= max; otherwise, no values are generated.enum arrays will produce an empty result set.Performance:
min/max).callback for dynamic filtering.Class Autoloading:
[Class::class, 'method']) require the class to be autoloadable.Inspect Config:
Validate $config structure before building:
if (empty($config['key']['values'])) {
throw new \InvalidArgumentException("Missing values for key 'key'");
}
Log Variations: Debug output for complex configs:
$variations = $builder->build($config);
\Log::debug('Generated variations:', ['data' => $variations]);
Custom Value Types:
Extend VariationFactory to support new types (e.g., date, uuid):
class CustomFactory extends VariationFactory {
public function generateDate($config) {
return Carbon::now()->addDays(rand(0, 30))->toDateString();
}
}
Post-Processing: Filter or transform variations after generation:
$variations = $builder->build($config);
$filtered = array_filter($variations, fn($v) => $v['status'] === 'active');
Laravel Collections:
Convert results to a Collection for Laravel-specific methods:
collect($builder->build($config))->each(fn($item) => Model::create($item));
[Class::class, 'method'].[new Class(), 'method'].fn() => [1, 2, 3] (requires callback type).min/max or values in config.How can I help you explore Laravel packages today?