Search code examples
phpsymfonyapi-platform.com

API Platform Validation doesn't work when using StateProcessor


I'm curious if it is a potential issue/improvement for API platform? As you know API platform has State Processors

But if you're using state processors the validation won't work. Here is my code:

public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = [])
{
    if ($operation instanceof Post && $data->getPlainPassword()) {
        $hashedPassword = $this->passwordHasher->hashPassword(
            $data,
            $data->getPlainPassword()
        );

        $data->setPassword($hashedPassword);
        $data->eraseCredentials();
    }

    return $this->processor->process($data, $operation, $uriVariables, $context);
}

In my User entity I use #[UniqueEntity('email')] constraint. So if I won't use Symfony Validator in this processor the exception would be thrown.

An exception occurred while executing a query: Duplicate entry '[email protected]' for key 'user.UNIQ_8D93D649E7927C74'

So the solution is:

$errors = $this->validator->validate($data);

if (count($errors) > 0) {
    throw new ValidationException($errors);
}

Solution

  • Okay i found a soltion, ensure that validation is called before delegating to the inner processor. You can call the validation interface, directly in your process to use them there. If you use Process Classes, the validationListener from ApiPlatform, dosnt get called anymore, so you have to setup this little code in your process by your self.

        <?php
    
        ....
        use Symfony\Component\Validator\Validator\ValidatorInterface;
        
        class MyProcessor implements ProcessorInterface
        {
            ...
            private ValidatorInterface $validator;
        
            public function __construct(...., ValidatorInterface $validator)
            {
                ....
                $this->validator = $validator;
            }
        
            public function process($data, Operation $operation, array $uriVariables = [], array $context = []): void
            {
                // Validate data
                $violations = $this->validator->validate($data);
                if (count($violations) > 0) {
                    throw new \ApiPlatform\Exception\ValidationException($violations);
                }
        
                .....
            }
        }