Description
Symfony version(s) affected: 5.2.0
Description
I was moving my projects to PHP8, using Attribute constraints (thanks to @derrabus) instead of Annotation ones. Regarding the Symfony\Component\Validator\Constraints\Choice
constraint, I encountered a difference between the two. This started here.
I often use associative arrays as choices - using the translation key as choice key (see How to reproduce below) ; one reason would be to share this constant array with the ChoiceType
choices
option. It was completely ok with Annotations. But the compatibility rule implemented below for the new Attribute usage is now concidering my choices keys as constraint options and breaks my code. I get that this is required to support both Annotation and Attribute but this changes the way this constraint is working.
symfony/src/Symfony/Component/Validator/Constraints/Choice.php
Lines 69 to 70 in d1cb2d6
How to reproduce
// stupid example
abstract class FormatEnum
{
public const ALL = [
'enum.format.example1' => 'f1',
'enum.format.example2' => 'd6',
'enum.format.example3' => 'u9',
];
}
// Annotation is fine 👍🏻
/** @Choice(choices=FormatEnum::ALL) */
// Attribute is ko 👎🏻
#[Choice(choices: FormatEnum::ALL)]
Possible Solution
Do not limit the test to \is_string(key($choices))
but check if key($choices)
is in a "whitelist" of arguments (the one from the constructor) ;
Edit 03/06/21:
$parameters = [
'choices', 'callback', 'multiple', 'strict', 'min', 'max', 'message',
'multipleMessage', 'minMessage', 'maxMessage', 'groups', 'payload', 'options',
];
if (\is_array($choices) && \is_string(key($choices)) && \in_array(key($choices), $parameters, true)) {
$options = array_merge($choices, $options);
} elseif (null !== $choices) {
$options['value'] = $choices;
}