📖 2 minutes read
When working with dynamic configuration or polymorphic data structures, PHP 8.1+ backed enums can do more than just define constants—they can encapsulate validation rules and type casting logic, creating a self-documenting, single-source-of-truth for field definitions.
The Pattern
enum ConfigType: string
{
case DISCOUNT_RATE = 'discount_rate';
case MAX_QUANTITY = 'max_quantity';
case ENABLED = 'enabled';
// Define the expected PHP type for each config
public function castType(): string
{
return match($this) {
self::DISCOUNT_RATE => 'float',
self::MAX_QUANTITY => 'int',
self::ENABLED => 'bool',
};
}
// Generate validation rules based on type
public function validationRules(): array
{
return match($this->castType()) {
'float' => ['numeric', 'min:0', 'max:100'],
'int' => ['integer', 'min:0'],
'bool' => ['boolean'],
default => ['string'],
};
}
// Get all enum cases with their cast types
public static function casts(): array
{
return collect(self::cases())
->mapWithKeys(fn($case) => [
$case->value => $case->castType()
])
->toArray();
}
}
Using in Models
class Config extends Model
{
protected $casts = [
'type' => ConfigType::class,
];
// Cast the stored string value to the correct type
public function getValue(): mixed
{
return match($this->type->castType()) {
'float' => (float) $this->value,
'int' => (int) $this->value,
'bool' => filter_var($this->value, FILTER_VALIDATE_BOOLEAN),
default => $this->value,
};
}
}
Using in Controllers
public function update(Request $request, $model)
{
// Generate validation rules dynamically from enum
$rules = collect(ConfigType::cases())
->mapWithKeys(fn($type) => [
$type->value => [
...$type->validationRules(),
'nullable'
]
])
->toArray();
$validated = $request->validate($rules);
// Save each config with proper type casting
foreach (ConfigType::cases() as $type) {
if (array_key_exists($type->value, $validated)) {
$model->setConfig($type, $validated[$type->value]);
}
}
}
Why This Works
- Single Source of Truth: Type definitions, validation, and casting logic live together
- Self-Documenting: New developers can read the enum to understand all available configuration fields
- Type-Safe: PHP 8.1+ backed enums with IDE autocomplete
- Maintainable: Adding a new config type is just one new case
- Testable: Easy to unit test each enum method independently
This pattern shines when building admin panels, user preferences, or any polymorphic configuration system where each field has different validation and type requirements.
Leave a Reply