Skip to content

XML and Yaml format doesn't work with Optional/Required collection constraints #7575

Closed
@wouterj

Description

@wouterj

Assume we have this entity:

class Author
{
    /**
     * @Assert\Collection(fields={
     *     "alternate_email" = @Optional({@Assert\Email})
     * })
    public $profileData = array();
}

The annotations and PHP format is working as expected. However, the Yaml and Xml format isn't working. On the documentation, we (ryan, @afishnamedsquish and I) have put some time in trying to get a working Yaml and Xml format, but it seems like it's not possible.

If we have this:

Acme\AuthorBundle\Entity\Author:
    properties:
        profileData:
             - Collection:
                fields:
                    alternate_email:
                        - Collection\Optional:
                            - Email: ~

We get this error:

Fatal error: Class 'Symfony\Component\Validator\Constraints\Collection\OptionalValidator'

It's going wrong in Collection line 50:

if (!$field instanceof Optional && !$field instanceof Required) {
    $this->fields[$fieldName] = $field = new Required($field);
}

$field is an instance of Optional or Required when using PHP or annotations. When using Yaml, $field is an array:

array (size=1)
  0 => 
    object(Symfony\Component\Validator\Constraints\Collection\Optional)[4300]
      public 'constraints' => 
        array (size=1)
          0 => 
            object(Symfony\Component\Validator\Constraints\Email)[4301]
              ...
      public 'groups' => 
        array (size=1)
          0 => string 'Default' (length=7)

Because it's not an instance of Optional or Required, it becomes:

object(Symfony\Component\Validator\Constraints\Collection\Required)[4302]
  public 'constraints' => 
    array (size=1)
      0 => 
        object(Symfony\Component\Validator\Constraints\Collection\Optional)[4300]
          public 'constraints' => 
            array (size=1)
              ...
          public 'groups' => 
            array (size=1)
              ...
  public 'groups' => 
    array (size=1)
      0 => string 'Default' (length=7)

And that's when we are in trouble, because the ValidatorFactory will search for OptionalValidator.

I have tried every Yaml syntax I know to make $field a class and not an array, but I can't find it. I think some change in the YamlFileLoader is needed to make these edge cases work.

This is the same for 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 http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">

    <class name="Acme\AuthorBundle\Entity\Author">
        <property name="profileData">
            <constraint name="Collection">
                <option name="fields">
                    <value key="alternate_email">
                        <constraint name="Collection\Optional">
                            <constraint name="Email" />
                        </constraint>
                    </value>
                </option>
            </constraint>
        </property>
    </class>
</constraint-mapping>

If you want some background on this issue, see symfony/symfony-docs#2432 and this gist.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Good first issueIdeal for your first contribution! (some Symfony experience may be required)Validator

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions