Description
Description
Not to be confused with Collection
to validate the individual elements of an array against arbitrary constraints, I wrote a Structure
constraint for use in personal projects which is used to validate (optionally) the size and type structure of an array's keys and values.
I think it could potentially be a useful addition to Symfony Validator core, but I want to gauge the interest.
I've provided example usage below to illustrate how it works. If there's interest in a PR, I'll create a branch with the code and test cases.
class SomeObject {
// This constraint says $address must have keys which are all strings, must have at most five elements, and all values must be strings.
#[Structure(keysType: 'string', valuesType: 'string', max: 5)]
private array $address;
// This constraint says all five of the specified keys must exist in the array. The array may optionally contain other keys.
#[Structure(keys: ['line1', 'line2', 'city', 'state', 'zipcode'])]
private array $address;
// This constraint mandates the keys are present and the value of the corresponding type. Fully qualified class or enums are permitted, as are recursively evaluated inner arrays. Type strings may use the pipe character to separate multiple permitted types.
#[Structure(structure: [
'nickname' => 'string',
'shareComments' => 'bool',
'age' => 'int',
'userType' => UserTypeEnum::class,
'address' => [
'line1' => 'string',
'line2' => 'string',
'postcode' => 'string',
'allowPostalCommunication' => 'bool|null',
]
])]
private array $profile;
}
The supported options on the constraint are min
and max
for array size, keysType
to specify all keys must be either ints or strings, valuesType
to specify all values must be of a type (or one of a pipe-delimited set of types), keys
to specify a list of keys which must all be present in the array, and structure
to define a specific key => type structure, which can be nested (this is limited to the kind of structure shown above, so a limitation of this constraint is that you can't say in the above example, for instance, the inner "address" array must merely contain between 1 and 5 elements like you can on the root constraint, you do have to specify the full structure you expect).
Thoughts and feedback welcome, thanks.
Example
$value = [
'foo' => 1,
'bar' => true,
'baz' => 'symfony',
'bip' => [
'bap' => null,
],
];
$constraint = new Structure(
min: 1,
max: 3,
keys: ['foo', 'bar', 'bop', 'fib']
);
$violations = $validator->validate($value, $constraint);
// Violations are:
// The array must have at most 3 elements
// The following keys are required: bop, fib.
$constraint = new Structure(
structure: [
'foo' => 'bool',
'baz' => 'string|int',
'bip' => [
'bap' => 'int',
],
]
);
$violations = $validator->validate($value, $constraint);
// Violations are:
// The value "1" at key "foo" is not of type boolean.
// The value "null" at key "bap" is not of type integer.