Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • SensioLabs Professional services to help you with Symfony
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by SensioLabs
  1. Home
  2. Documentation
  3. Reference
  4. Constraints
  5. Collection
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud

Table of Contents

  • Basic Usage
    • Presence and Absence of Fields
    • Required and Optional Field Constraints
  • Options
    • allowExtraFields
    • allowMissingFields
    • extraFieldsMessage
    • fields
    • groups
    • missingFieldsMessage
    • payload

Collection

Edit this page

Collection

This constraint is used when the underlying data is a collection (i.e. an array or an object that implements Traversable and ArrayAccess), but you'd like to validate different keys of that collection in different ways. For example, you might validate the email key using the Email constraint and the inventory key of the collection with the Range constraint.

This constraint can also make sure that certain collection keys are present and that extra keys are not present.

See also

If you want to validate that all the elements of the collection are unique use the Unique constraint.

Applies to property or method
Class Collection
Validator CollectionValidator

Basic Usage

The Collection constraint allows you to validate the different keys of a collection individually. Take the following example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Entity/Author.php
namespace App\Entity;

class Author
{
    protected $profileData = [
        'personal_email' => '...',
        'short_bio' => '...',
    ];

    public function setProfileData($key, $value)
    {
        $this->profileData[$key] = $value;
    }
}

To validate that the personal_email element of the profileData array property is a valid email address and that the short_bio element is not blank but is no longer than 100 characters in length, you would do the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// src/Entity/Author.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class Author
{
    #[Assert\Collection(
        fields: [
            'personal_email' => new Assert\Email,
            'short_bio' => [
                new Assert\NotBlank,
                new Assert\Length(
                    max: 100,
                    maxMessage: 'Your short bio is too long!'
                )
            ]
        ],
        allowMissingFields: true,
    )]
    protected $profileData = [
        'personal_email' => '...',
        'short_bio' => '...',
    ];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# config/validator/validation.yaml
App\Entity\Author:
    properties:
        profileData:
            - Collection:
                fields:
                    personal_email:
                        - Email: ~
                    short_bio:
                        - NotBlank: ~
                        - Length:
                            max:   100
                            maxMessage: Your short bio is too long!
                allowMissingFields: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!-- config/validator/validation.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">

    <class name="App\Entity\Author">
        <property name="profileData">
            <constraint name="Collection">
                <option name="fields">
                    <value key="personal_email">
                        <constraint name="Email"/>
                    </value>
                    <value key="short_bio">
                        <constraint name="NotBlank"/>
                        <constraint name="Length">
                            <option name="max">100</option>
                            <option name="maxMessage">Your short bio is too long!</option>
                        </constraint>
                    </value>
                </option>
                <option name="allowMissingFields">true</option>
            </constraint>
        </property>
    </class>
</constraint-mapping>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// src/Entity/Author.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class Author
{
    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('profileData', new Assert\Collection([
            'fields' => [
                'personal_email' => new Assert\Email(),
                'short_bio' => [
                    new Assert\NotBlank(),
                    new Assert\Length([
                        'max' => 100,
                        'maxMessage' => 'Your short bio is too long!',
                    ]),
                ],
            ],
            'allowMissingFields' => true,
        ]));
    }
}

Presence and Absence of Fields

By default, this constraint validates more than whether or not the individual fields in the collection pass their assigned constraints. In fact, if any keys of a collection are missing or if there are any unrecognized keys in the collection, validation errors will be thrown.

If you would like to allow for keys to be absent from the collection or if you would like "extra" keys to be allowed in the collection, you can modify the allowMissingFields and allowExtraFields options respectively. In the above example, the allowMissingFields option was set to true, meaning that if either of the personal_email or short_bio elements were missing from the $personalData property, no validation error would occur.

Required and Optional Field Constraints

Constraints for fields within a collection can be wrapped in the Required or Optional constraint to control whether they should always be applied (Required) or only applied when the field is present (Optional).

For instance, if you want to require that the personal_email field of the profileData array is not blank and is a valid email but the alternate_email field is optional but must be a valid email if supplied, you can do the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/Entity/Author.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class Author
{
    #[Assert\Collection(
        fields: [
            'personal_email' => new Assert\Required([
                new Assert\NotBlank,
                new Assert\Email,
            ]),
            'alternate_email' => new Assert\Optional(
                new Assert\Email
            ),
        ],
    )]
    protected $profileData = ['personal_email' => 'email@example.com'];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
# config/validator/validation.yaml
App\Entity\Author:
    properties:
        profile_data:
            - Collection:
                fields:
                    personal_email:
                        - Required:
                            - NotBlank: ~
                            - Email: ~
                    alternate_email:
                        - Optional:
                            - Email: ~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!-- config/validator/validation.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">

    <class name="App\Entity\Author">
        <property name="profile_data">
            <constraint name="Collection">
                <option name="fields">
                    <value key="personal_email">
                        <constraint name="Required">
                            <constraint name="NotBlank"/>
                            <constraint name="Email"/>
                        </constraint>
                    </value>
                    <value key="alternate_email">
                        <constraint name="Optional">
                            <constraint name="Email"/>
                        </constraint>
                    </value>
                </option>
            </constraint>
        </property>
    </class>
</constraint-mapping>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// src/Entity/Author.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class Author
{
    protected $profileData = ['personal_email'];

    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('profileData', new Assert\Collection([
            'fields' => [
                'personal_email'  => new Assert\Required([
                    new Assert\NotBlank(),
                    new Assert\Email(),
                ]),
                'alternate_email' => new Assert\Optional(new Assert\Email()),
            ],
        ]));
    }
}

Even without allowMissingFields set to true, you can now omit the alternate_email property completely from the profileData array, since it is Optional. However, if the personal_email field does not exist in the array, the NotBlank constraint will still be applied (since it is wrapped in Required) and you will receive a constraint violation.

When you define groups in nested constraints they are automatically added to the Collection constraint itself so it can be traversed for all nested groups. Take the following example:

1
2
3
4
5
6
7
8
use Symfony\Component\Validator\Constraints as Assert;

$constraint = new Assert\Collection([
    'fields' => [
        'name' => new Assert\NotBlank(['groups' => 'basic']),
        'email' => new Assert\NotBlank(['groups' => 'contact']),
    ],
]);

This will result in the following configuration:

1
2
3
4
5
6
7
8
9
10
11
12
13
$constraint = new Assert\Collection([
    'fields' => [
        'name' => new Assert\Required([
            'constraints' => new Assert\NotBlank(['groups' => 'basic']),
            'groups' => ['basic', 'strict'],
        ]),
        'email' => new Assert\Required([
            "constraints" => new Assert\NotBlank(['groups' => 'contact']),
            'groups' => ['basic', 'strict'],
        ]),
    ],
    'groups' => ['basic', 'strict'],
]);

The default allowMissingFields option requires the fields in all groups. So when validating in contact group, $name can be empty but the key is still required. If this is not the intended behavior, use the Optional constraint explicitly instead of Required.

Options

allowExtraFields

type: boolean default: false

If this option is set to false and the underlying collection contains one or more elements that are not included in the fields option, a validation error will be returned. If set to true, extra fields are OK.

allowMissingFields

type: boolean default: false

If this option is set to false and one or more fields from the fields option are not present in the underlying collection, a validation error will be returned. If set to true, it's OK if some fields in the fields option are not present in the underlying collection.

extraFieldsMessage

type: string default: This field was not expected.

The message shown if allowExtraFields is false and an extra field is detected.

You can use the following parameters in this message:

Parameter Description
{{ field }} The key of the extra field detected

fields

type: array [default option]

This option is required and is an associative array defining all of the keys in the collection and, for each key, exactly which validator(s) should be executed against that element of the collection.

groups

type: array | string default: null

It defines the validation group or groups of this constraint. Read more about validation groups.

missingFieldsMessage

type: string default: This field is missing.

The message shown if allowMissingFields is false and one or more fields are missing from the underlying collection.

You can use the following parameters in this message:

Parameter Description
{{ field }} The key of the missing field defined in fields

payload

type: mixed default: null

This option can be used to attach arbitrary domain-specific data to a constraint. The configured payload is not used by the Validator component, but its processing is completely up to you.

For example, you may want to use several error levels to present failed constraints differently in the front-end depending on the severity of the error.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version
    We stand with Ukraine.
    Version:

    Symfony 6.3 is backed by

    Symfony 6.3 is backed by

    Symfony 6.3 is backed by

    Symfony 6.3 is backed by

    Online exam, become Sylius certified today

    Online exam, become Sylius certified today

    Symfony Code Performance Profiling

    Symfony Code Performance Profiling

    Symfony footer

    ↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

    Avatar of Daniil Gentili, a Symfony contributor

    Thanks Daniil Gentili for being a Symfony contributor

    1 commit • 20 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • Symfony at a Glance
      • Symfony Components
      • Case Studies
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • SymfonyConnect
      • Support
      • How to be Involved
      • Code of Conduct
      • Events & Meetups
      • Projects using Symfony
      • Downloads Stats
      • Contributors
      • Backers
    • Blog

      • Events & Meetups
      • A week of symfony
      • Case studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Documentation
      • Living on the edge
      • Releases
      • Security Advisories
      • SymfonyInsight
      • Twig
      • SensioLabs
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Deployed on

    Follow Symfony

    Search by Algolia