Oleg Vartanov
Oleg Vartanov

Reputation: 35

"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?

Upvotes: 0

Views: 70

Answers (1)

Khribi Wessim
Khribi Wessim

Reputation: 702

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,
)

Upvotes: 1

Related Questions