Symfony validation callback

6.5k views Asked by At

I'm trying to validate my entity via static callback.

I was able to make it work following the Symfony guide but something isn't clear to me.

public static function validate($object, ExecutionContextInterface $context, $payload)
{
    // somehow you have an array of "fake names"
    $fakeNames = array(/* ... */);

    // check if the name is actually a fake name
    if (in_array($object->getFirstName(), $fakeNames)) {
        $context->buildViolation('This name sounds totally fake!')
            ->atPath('firstName')
            ->addViolation()
        ;
    }
}

It works fine when I populate my $fakeNames array but what if I want to make it "dynamic"? Let's say I want to pick that array from the parameters or from the database or wherever. How am I supposed to pass stuff (eg. the container or entityManager) to this class from the moment that the constructor doesn't work and it has to be necessarily static?

Of course my approach may be completely wrong but I'm just using the symfony example and few other similar issues found on the internet that I'm trying to adapt to my case.

2

There are 2 answers

0
kunicmarko20 On BEST ANSWER

You can create a Constraint and Validator and register it as service so you can inject entityManager or anything you need, you can read more here:

https://symfony.com/doc/2.8/validation/custom_constraint.html

or if you are on symfony 3.3 it is already a service and you can just typehint it in your constructor: https://symfony.com/doc/current/validation/custom_constraint.html

0
Roberto Rizzi On

This is the solution I was able to find in the end. It works smoothly and I hope it may be useful for someone else.

I've set the constraint on my validation.yml

User\UserBundle\Entity\Group:
    constraints:
        - User\UserBundle\Validator\Constraints\Roles\RolesConstraint: ~

Here is my RolesConstraint class

namespace User\UserBundle\Validator\Constraints\Roles;

use Symfony\Component\Validator\Constraint;

class RolesConstraint extends Constraint
{
    /** @var string $message */
    public $message = 'The role "{{ role }}" is not recognised.';

    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }
}

and here is my RolesConstraintValidator class

<?php

namespace User\UserBundle\Validator\Constraints\Roles;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class RolesConstraintValidator extends ConstraintValidator
{
    /** @var ContainerInterface */
    private $containerInterface;

    /**
     * @param ContainerInterface $containerInterface
    */
    public function __construct(ContainerInterface $containerInterface)
    {
        $this->containerInterface = $containerInterface;
    }

    /**
     * @param \User\UserBundle\Entity\Group $object
     * @param Constraint $constraint
    */
    public function validate($object, Constraint $constraint)
    {
        if (!in_array($object->getRole(), $this->containerInterface->getParameter('roles'))) {
            $this->context
                ->buildViolation($constraint->message)
                ->setParameter('{{ role }}', $object->getRole())
                ->addViolation();
        }
    }
}

Essentially, I set up a constraint which, every time a new user user is registered along with the role, that role must be among those set in the parameters. If not, it builds a violation.