symfony icon indicating copy to clipboard operation
symfony copied to clipboard

[Validator] Introduce `BackedEnumValue` constraint

Open AurelienPillevesse opened this issue 2 years ago • 27 comments

Q A
Branch? 8.1
Bug fix? no
New feature? yes
Deprecations? no
Issues -
License MIT

My use case: I receive data in my DTOs that we only want if this value exists in an Enum and reject the whole thing at validation otherwise.

AurelienPillevesse avatar Mar 10 '24 14:03 AurelienPillevesse

Did you read the discussion on #43047?

derrabus avatar Mar 10 '24 16:03 derrabus

Didn't see it before, my bad

AurelienPillevesse avatar Mar 10 '24 16:03 AurelienPillevesse

It's a dedicated constraint so why not but I understand if your point of view is to not accept it and adding the code below (as mentioned in the other discussion) if people want to accept an Enum value with #[MapRequestPayload] for example :

public static function values(): array
{
    return array_column(self::cases(), 'value');
}

Because you are speaking about this topic, can you maybe give me feedback about this PR : https://github.com/symfony/symfony-docs/pull/19590 (if it's added in the documentation, we will probably less try to find a way to achieve it)

AurelienPillevesse avatar Mar 10 '24 16:03 AurelienPillevesse

I understand if your point of view is to not accept it

I didn't say that. It's just that there has been a PR on that topic a while ago, and if we revisit the topic, we should take that prior discussion into account.

derrabus avatar Mar 10 '24 16:03 derrabus

Thanks for your feedbacks during this PR @derrabus

AurelienPillevesse avatar Mar 13 '24 12:03 AurelienPillevesse

This looks good, hopefully this gets through this time!

mdeboer avatar Mar 15 '24 12:03 mdeboer

If you want me to do any other change here, please tell me.

Otherwise, please review and approve this PR so maintainers can see it as ready. Thanks!

AurelienPillevesse avatar Mar 17 '24 11:03 AurelienPillevesse

I looked at it and it looks good, just one minor thing about the location of the fixture enums in the tests.

Not going to reject it based on that, nor approve it. Don't know what is recommended right now.

Once that is cleared up I'll approve it if that helps 👍🏻 Great work!

mdeboer avatar Mar 17 '24 14:03 mdeboer

While the validator indeed checks that the backed enum ends up being one of the possible choices, an interesting case popped up when I was testing the code:

enum SearchType: string {
    case Url = 'url';
    case Query = 'query';
}

final class SearchRequest {

    #[Assert\NotBlank]
    #[BackedEnumValue(type: SearchType::class)]
    public $searchType;

    #[Assert\NotBlank]
    public string $search;
}


// ...

declare(strict_types=1);

/**
 * @param SearchRequest $data
 * @return Search|void
 */
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = [])
{
    return new Search(
        searchType: $data->searchType,
        search: $data->search,
        products: [],
    );
}

The above code fails with the following message:

App\\ApiResource\\Search::__construct(): Argument #1 ($searchType) must be of type App\\Dto\\SearchType, string given,

Which makes me wonder, who is responsible for casting string into my enum? Am I expected to do so in my own Processor?

zexa avatar Jun 04 '24 19:06 zexa

Which makes me wonder, who is responsible for casting string into my enum? Am I expected to do so in my own Processor?

Yes! The validator won't transform any values for you, it only validates.

Note that we're discussing a new feature here and I'd like to keep that discussion focused. Please use the discussions board for support questions.

derrabus avatar Jun 04 '24 20:06 derrabus