symfonysymfony-validatorsymfony-http-foundationsymfony7symfony-http-kernel

"This value should be of type string" in Symfony DataTime validation, while mapping a request


In Symfony 7 app, I'm mapping request with MapQueryString/MapRequestPayload attributes. Controller's endpoint returns validation errors if request's parameter is of the wrong type. Here it is of type DateTime.

// Request query dto.
class Dto
{
    public function __construct(
        public ?DateTime $date = null
    ) {
    }
}

// Controller's endpoint.
public function fixtures(
    #[MapQueryString(
        validationFailedStatusCode: Response::HTTP_UNPROCESSABLE_ENTITY
    )] Dto $dto,
)

Validation works well when a valid date string is passed. But when it's not a valid date, it returns symfony validator response with "This value should be of type string" for that field, even when value is a string. Obviously it's a wrong message. What am I doing wrong? Is there a way to make the message right?


Solution

  • The problem here is that the #[MapQueryString] attribute maps the incoming query parameters directly into your Dto class properties. If for some reason the date parameter cannot be cast to a DateTime object, the Symfony validator thinks it's a type mismatch and returns the default "This value should be of type string" message, which is not intuitive in this context.

    You can fix this by adding a Custom Normalizer or a Custom Exception Listener or a Custom Validation Contraints

    For the Custom Validation Contraints, change the property type to string and convert it to DateTime manually in your business logic.

    use Symfony\Component\Validator\Constraints as Assert;
    
    class Dto
    {
        public function __construct(
            #[Assert\DateTime(
                message: "The date '{{ value }}' is not a valid date string."
            )]
            public ?string $date = null
        ) {
        }
    }
    
    // Controller's endpoint.
    public function fixtures(
        #[MapQueryString(
            validationFailedStatusCode: Response::HTTP_UNPROCESSABLE_ENTITY
        )] Dto $dto,
    )