Skip to content

New Structure constraint for validating array structure #50460

Closed as not planned
@dwgebler

Description

@dwgebler

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions