Description
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.